blob: 335f53969d356ad09b1da0ae9e921c5b7c6d949b [file] [log] [blame]
ludi50c27672017-05-12 09:15:00 -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 android.net;
18
19import static android.system.OsConstants.AF_INET;
20import static android.system.OsConstants.IPPROTO_UDP;
21import static android.system.OsConstants.SOCK_DGRAM;
Brett Chabot147f6cf2019-03-04 14:14:56 -080022
ludi50c27672017-05-12 09:15:00 -070023import static org.junit.Assert.assertEquals;
24import static org.junit.Assert.assertNotNull;
25import static org.junit.Assert.fail;
26import static org.mockito.Matchers.anyInt;
27import static org.mockito.Matchers.anyObject;
28import static org.mockito.Matchers.anyString;
29import static org.mockito.Matchers.eq;
30import static org.mockito.Mockito.mock;
31import static org.mockito.Mockito.verify;
32import static org.mockito.Mockito.when;
33
Remi NGUYEN VAN154cf1d2021-06-29 17:16:28 +090034import android.os.Build;
ludi50c27672017-05-12 09:15:00 -070035import android.system.Os;
Brett Chabot147f6cf2019-03-04 14:14:56 -080036import android.test.mock.MockContext;
37
38import androidx.test.filters.SmallTest;
Hugo Benichi1c0f4e22017-10-11 11:26:25 +090039
ludi50c27672017-05-12 09:15:00 -070040import com.android.server.IpSecService;
Remi NGUYEN VAN154cf1d2021-06-29 17:16:28 +090041import com.android.testutils.DevSdkIgnoreRule;
42import com.android.testutils.DevSdkIgnoreRunner;
Hugo Benichi1c0f4e22017-10-11 11:26:25 +090043
ludi50c27672017-05-12 09:15:00 -070044import org.junit.Before;
45import org.junit.Test;
46import org.junit.runner.RunWith;
ludi50c27672017-05-12 09:15:00 -070047
Brett Chabot147f6cf2019-03-04 14:14:56 -080048import java.net.InetAddress;
49import java.net.Socket;
50import java.net.UnknownHostException;
51
ludi50c27672017-05-12 09:15:00 -070052/** Unit tests for {@link IpSecManager}. */
53@SmallTest
Remi NGUYEN VAN154cf1d2021-06-29 17:16:28 +090054@RunWith(DevSdkIgnoreRunner.class)
Paul Hu516d5dc2022-05-26 12:57:01 +000055@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
ludi50c27672017-05-12 09:15:00 -070056public class IpSecManagerTest {
57
58 private static final int TEST_UDP_ENCAP_PORT = 34567;
59 private static final int DROID_SPI = 0xD1201D;
Benedict Wong76df78f2018-03-01 18:53:07 -080060 private static final int DUMMY_RESOURCE_ID = 0x1234;
ludi50c27672017-05-12 09:15:00 -070061
62 private static final InetAddress GOOGLE_DNS_4;
Benedict Wong76df78f2018-03-01 18:53:07 -080063 private static final String VTI_INTF_NAME = "ipsec_test";
64 private static final InetAddress VTI_LOCAL_ADDRESS;
65 private static final LinkAddress VTI_INNER_ADDRESS = new LinkAddress("10.0.1.1/24");
ludi50c27672017-05-12 09:15:00 -070066
67 static {
68 try {
69 // Google Public DNS Addresses;
70 GOOGLE_DNS_4 = InetAddress.getByName("8.8.8.8");
Benedict Wong76df78f2018-03-01 18:53:07 -080071 VTI_LOCAL_ADDRESS = InetAddress.getByName("8.8.4.4");
ludi50c27672017-05-12 09:15:00 -070072 } catch (UnknownHostException e) {
73 throw new RuntimeException("Could not resolve DNS Addresses", e);
74 }
75 }
76
77 private IpSecService mMockIpSecService;
78 private IpSecManager mIpSecManager;
Nathan Harold68a7edf2018-03-15 18:06:06 -070079 private MockContext mMockContext = new MockContext() {
80 @Override
81 public String getOpPackageName() {
82 return "fooPackage";
83 }
84 };
ludi50c27672017-05-12 09:15:00 -070085
86 @Before
87 public void setUp() throws Exception {
88 mMockIpSecService = mock(IpSecService.class);
Nathan Harold68a7edf2018-03-15 18:06:06 -070089 mIpSecManager = new IpSecManager(mMockContext, mMockIpSecService);
ludi50c27672017-05-12 09:15:00 -070090 }
91
92 /*
93 * Allocate a specific SPI
94 * Close SPIs
95 */
96 @Test
97 public void testAllocSpi() throws Exception {
ludi50c27672017-05-12 09:15:00 -070098 IpSecSpiResponse spiResp =
Benedict Wong76df78f2018-03-01 18:53:07 -080099 new IpSecSpiResponse(IpSecManager.Status.OK, DUMMY_RESOURCE_ID, DROID_SPI);
Jonathan Basserifbe3a822017-11-16 10:58:01 -0800100 when(mMockIpSecService.allocateSecurityParameterIndex(
ludi50c27672017-05-12 09:15:00 -0700101 eq(GOOGLE_DNS_4.getHostAddress()),
102 eq(DROID_SPI),
103 anyObject()))
104 .thenReturn(spiResp);
105
106 IpSecManager.SecurityParameterIndex droidSpi =
Nathan Harold3865a002018-01-05 19:25:13 -0800107 mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4, DROID_SPI);
ludi50c27672017-05-12 09:15:00 -0700108 assertEquals(DROID_SPI, droidSpi.getSpi());
109
110 droidSpi.close();
111
Benedict Wong76df78f2018-03-01 18:53:07 -0800112 verify(mMockIpSecService).releaseSecurityParameterIndex(DUMMY_RESOURCE_ID);
ludi50c27672017-05-12 09:15:00 -0700113 }
114
115 @Test
116 public void testAllocRandomSpi() throws Exception {
ludi50c27672017-05-12 09:15:00 -0700117 IpSecSpiResponse spiResp =
Benedict Wong76df78f2018-03-01 18:53:07 -0800118 new IpSecSpiResponse(IpSecManager.Status.OK, DUMMY_RESOURCE_ID, DROID_SPI);
Jonathan Basserifbe3a822017-11-16 10:58:01 -0800119 when(mMockIpSecService.allocateSecurityParameterIndex(
ludi50c27672017-05-12 09:15:00 -0700120 eq(GOOGLE_DNS_4.getHostAddress()),
121 eq(IpSecManager.INVALID_SECURITY_PARAMETER_INDEX),
122 anyObject()))
123 .thenReturn(spiResp);
124
125 IpSecManager.SecurityParameterIndex randomSpi =
Nathan Harold3865a002018-01-05 19:25:13 -0800126 mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4);
ludi50c27672017-05-12 09:15:00 -0700127
128 assertEquals(DROID_SPI, randomSpi.getSpi());
129
130 randomSpi.close();
131
Benedict Wong76df78f2018-03-01 18:53:07 -0800132 verify(mMockIpSecService).releaseSecurityParameterIndex(DUMMY_RESOURCE_ID);
ludi50c27672017-05-12 09:15:00 -0700133 }
134
135 /*
136 * Throws resource unavailable exception
137 */
138 @Test
Nathan Harold3865a002018-01-05 19:25:13 -0800139 public void testAllocSpiResUnavailableException() throws Exception {
ludi50c27672017-05-12 09:15:00 -0700140 IpSecSpiResponse spiResp =
141 new IpSecSpiResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE, 0, 0);
Jonathan Basserifbe3a822017-11-16 10:58:01 -0800142 when(mMockIpSecService.allocateSecurityParameterIndex(
Nathan Harold3865a002018-01-05 19:25:13 -0800143 anyString(), anyInt(), anyObject()))
ludi50c27672017-05-12 09:15:00 -0700144 .thenReturn(spiResp);
145
146 try {
Nathan Harold3865a002018-01-05 19:25:13 -0800147 mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4);
ludi50c27672017-05-12 09:15:00 -0700148 fail("ResourceUnavailableException was not thrown");
149 } catch (IpSecManager.ResourceUnavailableException e) {
150 }
151 }
152
153 /*
154 * Throws spi unavailable exception
155 */
156 @Test
Nathan Harold3865a002018-01-05 19:25:13 -0800157 public void testAllocSpiSpiUnavailableException() throws Exception {
ludi50c27672017-05-12 09:15:00 -0700158 IpSecSpiResponse spiResp = new IpSecSpiResponse(IpSecManager.Status.SPI_UNAVAILABLE, 0, 0);
Jonathan Basserifbe3a822017-11-16 10:58:01 -0800159 when(mMockIpSecService.allocateSecurityParameterIndex(
Nathan Harold3865a002018-01-05 19:25:13 -0800160 anyString(), anyInt(), anyObject()))
ludi50c27672017-05-12 09:15:00 -0700161 .thenReturn(spiResp);
162
163 try {
Nathan Harold3865a002018-01-05 19:25:13 -0800164 mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4);
ludi50c27672017-05-12 09:15:00 -0700165 fail("ResourceUnavailableException was not thrown");
166 } catch (IpSecManager.ResourceUnavailableException e) {
167 }
168 }
169
170 /*
171 * Should throw exception when request spi 0 in IpSecManager
172 */
173 @Test
174 public void testRequestAllocInvalidSpi() throws Exception {
175 try {
Nathan Harold3865a002018-01-05 19:25:13 -0800176 mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4, 0);
ludi50c27672017-05-12 09:15:00 -0700177 fail("Able to allocate invalid spi");
178 } catch (IllegalArgumentException e) {
179 }
180 }
181
182 @Test
183 public void testOpenEncapsulationSocket() throws Exception {
ludi50c27672017-05-12 09:15:00 -0700184 IpSecUdpEncapResponse udpEncapResp =
185 new IpSecUdpEncapResponse(
186 IpSecManager.Status.OK,
Benedict Wong76df78f2018-03-01 18:53:07 -0800187 DUMMY_RESOURCE_ID,
ludi50c27672017-05-12 09:15:00 -0700188 TEST_UDP_ENCAP_PORT,
189 Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
190 when(mMockIpSecService.openUdpEncapsulationSocket(eq(TEST_UDP_ENCAP_PORT), anyObject()))
191 .thenReturn(udpEncapResp);
192
193 IpSecManager.UdpEncapsulationSocket encapSocket =
194 mIpSecManager.openUdpEncapsulationSocket(TEST_UDP_ENCAP_PORT);
Benedict Wongc1658852018-03-27 16:55:48 -0700195 assertNotNull(encapSocket.getFileDescriptor());
ludi50c27672017-05-12 09:15:00 -0700196 assertEquals(TEST_UDP_ENCAP_PORT, encapSocket.getPort());
197
198 encapSocket.close();
199
Benedict Wong76df78f2018-03-01 18:53:07 -0800200 verify(mMockIpSecService).closeUdpEncapsulationSocket(DUMMY_RESOURCE_ID);
ludi50c27672017-05-12 09:15:00 -0700201 }
202
203 @Test
Benedict Wong412ff412018-04-02 18:12:34 -0700204 public void testApplyTransportModeTransformEnsuresSocketCreation() throws Exception {
205 Socket socket = new Socket();
206 IpSecConfig dummyConfig = new IpSecConfig();
207 IpSecTransform dummyTransform = new IpSecTransform(null, dummyConfig);
208
209 // Even if underlying SocketImpl is not initalized, this should force the init, and
210 // thereby succeed.
211 mIpSecManager.applyTransportModeTransform(
212 socket, IpSecManager.DIRECTION_IN, dummyTransform);
213
214 // Check to make sure the FileDescriptor is non-null
215 assertNotNull(socket.getFileDescriptor$());
216 }
217
218 @Test
219 public void testRemoveTransportModeTransformsForcesSocketCreation() throws Exception {
220 Socket socket = new Socket();
221
222 // Even if underlying SocketImpl is not initalized, this should force the init, and
223 // thereby succeed.
224 mIpSecManager.removeTransportModeTransforms(socket);
225
226 // Check to make sure the FileDescriptor is non-null
227 assertNotNull(socket.getFileDescriptor$());
228 }
229
230 @Test
ludi50c27672017-05-12 09:15:00 -0700231 public void testOpenEncapsulationSocketOnRandomPort() throws Exception {
ludi50c27672017-05-12 09:15:00 -0700232 IpSecUdpEncapResponse udpEncapResp =
233 new IpSecUdpEncapResponse(
234 IpSecManager.Status.OK,
Benedict Wong76df78f2018-03-01 18:53:07 -0800235 DUMMY_RESOURCE_ID,
ludi50c27672017-05-12 09:15:00 -0700236 TEST_UDP_ENCAP_PORT,
237 Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
238
239 when(mMockIpSecService.openUdpEncapsulationSocket(eq(0), anyObject()))
240 .thenReturn(udpEncapResp);
241
242 IpSecManager.UdpEncapsulationSocket encapSocket =
243 mIpSecManager.openUdpEncapsulationSocket();
244
Benedict Wongc1658852018-03-27 16:55:48 -0700245 assertNotNull(encapSocket.getFileDescriptor());
ludi50c27672017-05-12 09:15:00 -0700246 assertEquals(TEST_UDP_ENCAP_PORT, encapSocket.getPort());
247
248 encapSocket.close();
249
Benedict Wong76df78f2018-03-01 18:53:07 -0800250 verify(mMockIpSecService).closeUdpEncapsulationSocket(DUMMY_RESOURCE_ID);
ludi50c27672017-05-12 09:15:00 -0700251 }
252
253 @Test
254 public void testOpenEncapsulationSocketWithInvalidPort() throws Exception {
255 try {
256 mIpSecManager.openUdpEncapsulationSocket(IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
257 fail("IllegalArgumentException was not thrown");
258 } catch (IllegalArgumentException e) {
259 }
260 }
261
262 // TODO: add test when applicable transform builder interface is available
Benedict Wong76df78f2018-03-01 18:53:07 -0800263
264 private IpSecManager.IpSecTunnelInterface createAndValidateVti(int resourceId, String intfName)
265 throws Exception {
266 IpSecTunnelInterfaceResponse dummyResponse =
267 new IpSecTunnelInterfaceResponse(IpSecManager.Status.OK, resourceId, intfName);
268 when(mMockIpSecService.createTunnelInterface(
269 eq(VTI_LOCAL_ADDRESS.getHostAddress()), eq(GOOGLE_DNS_4.getHostAddress()),
Nathan Harold68a7edf2018-03-15 18:06:06 -0700270 anyObject(), anyObject(), anyString()))
Benedict Wong76df78f2018-03-01 18:53:07 -0800271 .thenReturn(dummyResponse);
272
273 IpSecManager.IpSecTunnelInterface tunnelIntf = mIpSecManager.createIpSecTunnelInterface(
274 VTI_LOCAL_ADDRESS, GOOGLE_DNS_4, mock(Network.class));
275
276 assertNotNull(tunnelIntf);
277 return tunnelIntf;
278 }
279
280 @Test
281 public void testCreateVti() throws Exception {
282 IpSecManager.IpSecTunnelInterface tunnelIntf =
283 createAndValidateVti(DUMMY_RESOURCE_ID, VTI_INTF_NAME);
284
285 assertEquals(VTI_INTF_NAME, tunnelIntf.getInterfaceName());
286
287 tunnelIntf.close();
Nathan Harold68a7edf2018-03-15 18:06:06 -0700288 verify(mMockIpSecService).deleteTunnelInterface(eq(DUMMY_RESOURCE_ID), anyString());
Benedict Wong76df78f2018-03-01 18:53:07 -0800289 }
290
291 @Test
292 public void testAddRemoveAddressesFromVti() throws Exception {
293 IpSecManager.IpSecTunnelInterface tunnelIntf =
294 createAndValidateVti(DUMMY_RESOURCE_ID, VTI_INTF_NAME);
295
Benedict Wong2ea91ae2018-04-03 20:30:54 -0700296 tunnelIntf.addAddress(VTI_INNER_ADDRESS.getAddress(),
297 VTI_INNER_ADDRESS.getPrefixLength());
Benedict Wong76df78f2018-03-01 18:53:07 -0800298 verify(mMockIpSecService)
Nathan Harold68a7edf2018-03-15 18:06:06 -0700299 .addAddressToTunnelInterface(
300 eq(DUMMY_RESOURCE_ID), eq(VTI_INNER_ADDRESS), anyString());
Benedict Wong76df78f2018-03-01 18:53:07 -0800301
Benedict Wong2ea91ae2018-04-03 20:30:54 -0700302 tunnelIntf.removeAddress(VTI_INNER_ADDRESS.getAddress(),
303 VTI_INNER_ADDRESS.getPrefixLength());
Benedict Wong76df78f2018-03-01 18:53:07 -0800304 verify(mMockIpSecService)
Nathan Harold68a7edf2018-03-15 18:06:06 -0700305 .addAddressToTunnelInterface(
306 eq(DUMMY_RESOURCE_ID), eq(VTI_INNER_ADDRESS), anyString());
Benedict Wong76df78f2018-03-01 18:53:07 -0800307 }
Nathan Harold68a7edf2018-03-15 18:06:06 -0700308}