blob: 730e2d56bd780b35097188bab3948ee9b2ca3aae [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
ludi50c27672017-05-12 09:15:00 -070034import android.system.Os;
Brett Chabot147f6cf2019-03-04 14:14:56 -080035import android.test.mock.MockContext;
36
37import androidx.test.filters.SmallTest;
38import androidx.test.runner.AndroidJUnit4;
Hugo Benichi1c0f4e22017-10-11 11:26:25 +090039
ludi50c27672017-05-12 09:15:00 -070040import com.android.server.IpSecService;
Hugo Benichi1c0f4e22017-10-11 11:26:25 +090041
ludi50c27672017-05-12 09:15:00 -070042import org.junit.Before;
43import org.junit.Test;
44import org.junit.runner.RunWith;
ludi50c27672017-05-12 09:15:00 -070045
Brett Chabot147f6cf2019-03-04 14:14:56 -080046import java.net.InetAddress;
47import java.net.Socket;
48import java.net.UnknownHostException;
49
ludi50c27672017-05-12 09:15:00 -070050/** Unit tests for {@link IpSecManager}. */
51@SmallTest
Hugo Benichi1c0f4e22017-10-11 11:26:25 +090052@RunWith(AndroidJUnit4.class)
ludi50c27672017-05-12 09:15:00 -070053public class IpSecManagerTest {
54
55 private static final int TEST_UDP_ENCAP_PORT = 34567;
56 private static final int DROID_SPI = 0xD1201D;
Benedict Wong76df78f2018-03-01 18:53:07 -080057 private static final int DUMMY_RESOURCE_ID = 0x1234;
ludi50c27672017-05-12 09:15:00 -070058
59 private static final InetAddress GOOGLE_DNS_4;
Benedict Wong76df78f2018-03-01 18:53:07 -080060 private static final String VTI_INTF_NAME = "ipsec_test";
61 private static final InetAddress VTI_LOCAL_ADDRESS;
62 private static final LinkAddress VTI_INNER_ADDRESS = new LinkAddress("10.0.1.1/24");
ludi50c27672017-05-12 09:15:00 -070063
64 static {
65 try {
66 // Google Public DNS Addresses;
67 GOOGLE_DNS_4 = InetAddress.getByName("8.8.8.8");
Benedict Wong76df78f2018-03-01 18:53:07 -080068 VTI_LOCAL_ADDRESS = InetAddress.getByName("8.8.4.4");
ludi50c27672017-05-12 09:15:00 -070069 } catch (UnknownHostException e) {
70 throw new RuntimeException("Could not resolve DNS Addresses", e);
71 }
72 }
73
74 private IpSecService mMockIpSecService;
75 private IpSecManager mIpSecManager;
Nathan Harold68a7edf2018-03-15 18:06:06 -070076 private MockContext mMockContext = new MockContext() {
77 @Override
78 public String getOpPackageName() {
79 return "fooPackage";
80 }
81 };
ludi50c27672017-05-12 09:15:00 -070082
83 @Before
84 public void setUp() throws Exception {
85 mMockIpSecService = mock(IpSecService.class);
Nathan Harold68a7edf2018-03-15 18:06:06 -070086 mIpSecManager = new IpSecManager(mMockContext, mMockIpSecService);
ludi50c27672017-05-12 09:15:00 -070087 }
88
89 /*
90 * Allocate a specific SPI
91 * Close SPIs
92 */
93 @Test
94 public void testAllocSpi() throws Exception {
ludi50c27672017-05-12 09:15:00 -070095 IpSecSpiResponse spiResp =
Benedict Wong76df78f2018-03-01 18:53:07 -080096 new IpSecSpiResponse(IpSecManager.Status.OK, DUMMY_RESOURCE_ID, DROID_SPI);
Jonathan Basserifbe3a822017-11-16 10:58:01 -080097 when(mMockIpSecService.allocateSecurityParameterIndex(
ludi50c27672017-05-12 09:15:00 -070098 eq(GOOGLE_DNS_4.getHostAddress()),
99 eq(DROID_SPI),
100 anyObject()))
101 .thenReturn(spiResp);
102
103 IpSecManager.SecurityParameterIndex droidSpi =
Nathan Harold3865a002018-01-05 19:25:13 -0800104 mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4, DROID_SPI);
ludi50c27672017-05-12 09:15:00 -0700105 assertEquals(DROID_SPI, droidSpi.getSpi());
106
107 droidSpi.close();
108
Benedict Wong76df78f2018-03-01 18:53:07 -0800109 verify(mMockIpSecService).releaseSecurityParameterIndex(DUMMY_RESOURCE_ID);
ludi50c27672017-05-12 09:15:00 -0700110 }
111
112 @Test
113 public void testAllocRandomSpi() throws Exception {
ludi50c27672017-05-12 09:15:00 -0700114 IpSecSpiResponse spiResp =
Benedict Wong76df78f2018-03-01 18:53:07 -0800115 new IpSecSpiResponse(IpSecManager.Status.OK, DUMMY_RESOURCE_ID, DROID_SPI);
Jonathan Basserifbe3a822017-11-16 10:58:01 -0800116 when(mMockIpSecService.allocateSecurityParameterIndex(
ludi50c27672017-05-12 09:15:00 -0700117 eq(GOOGLE_DNS_4.getHostAddress()),
118 eq(IpSecManager.INVALID_SECURITY_PARAMETER_INDEX),
119 anyObject()))
120 .thenReturn(spiResp);
121
122 IpSecManager.SecurityParameterIndex randomSpi =
Nathan Harold3865a002018-01-05 19:25:13 -0800123 mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4);
ludi50c27672017-05-12 09:15:00 -0700124
125 assertEquals(DROID_SPI, randomSpi.getSpi());
126
127 randomSpi.close();
128
Benedict Wong76df78f2018-03-01 18:53:07 -0800129 verify(mMockIpSecService).releaseSecurityParameterIndex(DUMMY_RESOURCE_ID);
ludi50c27672017-05-12 09:15:00 -0700130 }
131
132 /*
133 * Throws resource unavailable exception
134 */
135 @Test
Nathan Harold3865a002018-01-05 19:25:13 -0800136 public void testAllocSpiResUnavailableException() throws Exception {
ludi50c27672017-05-12 09:15:00 -0700137 IpSecSpiResponse spiResp =
138 new IpSecSpiResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE, 0, 0);
Jonathan Basserifbe3a822017-11-16 10:58:01 -0800139 when(mMockIpSecService.allocateSecurityParameterIndex(
Nathan Harold3865a002018-01-05 19:25:13 -0800140 anyString(), anyInt(), anyObject()))
ludi50c27672017-05-12 09:15:00 -0700141 .thenReturn(spiResp);
142
143 try {
Nathan Harold3865a002018-01-05 19:25:13 -0800144 mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4);
ludi50c27672017-05-12 09:15:00 -0700145 fail("ResourceUnavailableException was not thrown");
146 } catch (IpSecManager.ResourceUnavailableException e) {
147 }
148 }
149
150 /*
151 * Throws spi unavailable exception
152 */
153 @Test
Nathan Harold3865a002018-01-05 19:25:13 -0800154 public void testAllocSpiSpiUnavailableException() throws Exception {
ludi50c27672017-05-12 09:15:00 -0700155 IpSecSpiResponse spiResp = new IpSecSpiResponse(IpSecManager.Status.SPI_UNAVAILABLE, 0, 0);
Jonathan Basserifbe3a822017-11-16 10:58:01 -0800156 when(mMockIpSecService.allocateSecurityParameterIndex(
Nathan Harold3865a002018-01-05 19:25:13 -0800157 anyString(), anyInt(), anyObject()))
ludi50c27672017-05-12 09:15:00 -0700158 .thenReturn(spiResp);
159
160 try {
Nathan Harold3865a002018-01-05 19:25:13 -0800161 mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4);
ludi50c27672017-05-12 09:15:00 -0700162 fail("ResourceUnavailableException was not thrown");
163 } catch (IpSecManager.ResourceUnavailableException e) {
164 }
165 }
166
167 /*
168 * Should throw exception when request spi 0 in IpSecManager
169 */
170 @Test
171 public void testRequestAllocInvalidSpi() throws Exception {
172 try {
Nathan Harold3865a002018-01-05 19:25:13 -0800173 mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4, 0);
ludi50c27672017-05-12 09:15:00 -0700174 fail("Able to allocate invalid spi");
175 } catch (IllegalArgumentException e) {
176 }
177 }
178
179 @Test
180 public void testOpenEncapsulationSocket() throws Exception {
ludi50c27672017-05-12 09:15:00 -0700181 IpSecUdpEncapResponse udpEncapResp =
182 new IpSecUdpEncapResponse(
183 IpSecManager.Status.OK,
Benedict Wong76df78f2018-03-01 18:53:07 -0800184 DUMMY_RESOURCE_ID,
ludi50c27672017-05-12 09:15:00 -0700185 TEST_UDP_ENCAP_PORT,
186 Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
187 when(mMockIpSecService.openUdpEncapsulationSocket(eq(TEST_UDP_ENCAP_PORT), anyObject()))
188 .thenReturn(udpEncapResp);
189
190 IpSecManager.UdpEncapsulationSocket encapSocket =
191 mIpSecManager.openUdpEncapsulationSocket(TEST_UDP_ENCAP_PORT);
Benedict Wongc1658852018-03-27 16:55:48 -0700192 assertNotNull(encapSocket.getFileDescriptor());
ludi50c27672017-05-12 09:15:00 -0700193 assertEquals(TEST_UDP_ENCAP_PORT, encapSocket.getPort());
194
195 encapSocket.close();
196
Benedict Wong76df78f2018-03-01 18:53:07 -0800197 verify(mMockIpSecService).closeUdpEncapsulationSocket(DUMMY_RESOURCE_ID);
ludi50c27672017-05-12 09:15:00 -0700198 }
199
200 @Test
Benedict Wong412ff412018-04-02 18:12:34 -0700201 public void testApplyTransportModeTransformEnsuresSocketCreation() throws Exception {
202 Socket socket = new Socket();
203 IpSecConfig dummyConfig = new IpSecConfig();
204 IpSecTransform dummyTransform = new IpSecTransform(null, dummyConfig);
205
206 // Even if underlying SocketImpl is not initalized, this should force the init, and
207 // thereby succeed.
208 mIpSecManager.applyTransportModeTransform(
209 socket, IpSecManager.DIRECTION_IN, dummyTransform);
210
211 // Check to make sure the FileDescriptor is non-null
212 assertNotNull(socket.getFileDescriptor$());
213 }
214
215 @Test
216 public void testRemoveTransportModeTransformsForcesSocketCreation() throws Exception {
217 Socket socket = new Socket();
218
219 // Even if underlying SocketImpl is not initalized, this should force the init, and
220 // thereby succeed.
221 mIpSecManager.removeTransportModeTransforms(socket);
222
223 // Check to make sure the FileDescriptor is non-null
224 assertNotNull(socket.getFileDescriptor$());
225 }
226
227 @Test
ludi50c27672017-05-12 09:15:00 -0700228 public void testOpenEncapsulationSocketOnRandomPort() throws Exception {
ludi50c27672017-05-12 09:15:00 -0700229 IpSecUdpEncapResponse udpEncapResp =
230 new IpSecUdpEncapResponse(
231 IpSecManager.Status.OK,
Benedict Wong76df78f2018-03-01 18:53:07 -0800232 DUMMY_RESOURCE_ID,
ludi50c27672017-05-12 09:15:00 -0700233 TEST_UDP_ENCAP_PORT,
234 Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
235
236 when(mMockIpSecService.openUdpEncapsulationSocket(eq(0), anyObject()))
237 .thenReturn(udpEncapResp);
238
239 IpSecManager.UdpEncapsulationSocket encapSocket =
240 mIpSecManager.openUdpEncapsulationSocket();
241
Benedict Wongc1658852018-03-27 16:55:48 -0700242 assertNotNull(encapSocket.getFileDescriptor());
ludi50c27672017-05-12 09:15:00 -0700243 assertEquals(TEST_UDP_ENCAP_PORT, encapSocket.getPort());
244
245 encapSocket.close();
246
Benedict Wong76df78f2018-03-01 18:53:07 -0800247 verify(mMockIpSecService).closeUdpEncapsulationSocket(DUMMY_RESOURCE_ID);
ludi50c27672017-05-12 09:15:00 -0700248 }
249
250 @Test
251 public void testOpenEncapsulationSocketWithInvalidPort() throws Exception {
252 try {
253 mIpSecManager.openUdpEncapsulationSocket(IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
254 fail("IllegalArgumentException was not thrown");
255 } catch (IllegalArgumentException e) {
256 }
257 }
258
259 // TODO: add test when applicable transform builder interface is available
Benedict Wong76df78f2018-03-01 18:53:07 -0800260
261 private IpSecManager.IpSecTunnelInterface createAndValidateVti(int resourceId, String intfName)
262 throws Exception {
263 IpSecTunnelInterfaceResponse dummyResponse =
264 new IpSecTunnelInterfaceResponse(IpSecManager.Status.OK, resourceId, intfName);
265 when(mMockIpSecService.createTunnelInterface(
266 eq(VTI_LOCAL_ADDRESS.getHostAddress()), eq(GOOGLE_DNS_4.getHostAddress()),
Nathan Harold68a7edf2018-03-15 18:06:06 -0700267 anyObject(), anyObject(), anyString()))
Benedict Wong76df78f2018-03-01 18:53:07 -0800268 .thenReturn(dummyResponse);
269
270 IpSecManager.IpSecTunnelInterface tunnelIntf = mIpSecManager.createIpSecTunnelInterface(
271 VTI_LOCAL_ADDRESS, GOOGLE_DNS_4, mock(Network.class));
272
273 assertNotNull(tunnelIntf);
274 return tunnelIntf;
275 }
276
277 @Test
278 public void testCreateVti() throws Exception {
279 IpSecManager.IpSecTunnelInterface tunnelIntf =
280 createAndValidateVti(DUMMY_RESOURCE_ID, VTI_INTF_NAME);
281
282 assertEquals(VTI_INTF_NAME, tunnelIntf.getInterfaceName());
283
284 tunnelIntf.close();
Nathan Harold68a7edf2018-03-15 18:06:06 -0700285 verify(mMockIpSecService).deleteTunnelInterface(eq(DUMMY_RESOURCE_ID), anyString());
Benedict Wong76df78f2018-03-01 18:53:07 -0800286 }
287
288 @Test
289 public void testAddRemoveAddressesFromVti() throws Exception {
290 IpSecManager.IpSecTunnelInterface tunnelIntf =
291 createAndValidateVti(DUMMY_RESOURCE_ID, VTI_INTF_NAME);
292
Benedict Wong2ea91ae2018-04-03 20:30:54 -0700293 tunnelIntf.addAddress(VTI_INNER_ADDRESS.getAddress(),
294 VTI_INNER_ADDRESS.getPrefixLength());
Benedict Wong76df78f2018-03-01 18:53:07 -0800295 verify(mMockIpSecService)
Nathan Harold68a7edf2018-03-15 18:06:06 -0700296 .addAddressToTunnelInterface(
297 eq(DUMMY_RESOURCE_ID), eq(VTI_INNER_ADDRESS), anyString());
Benedict Wong76df78f2018-03-01 18:53:07 -0800298
Benedict Wong2ea91ae2018-04-03 20:30:54 -0700299 tunnelIntf.removeAddress(VTI_INNER_ADDRESS.getAddress(),
300 VTI_INNER_ADDRESS.getPrefixLength());
Benedict Wong76df78f2018-03-01 18:53:07 -0800301 verify(mMockIpSecService)
Nathan Harold68a7edf2018-03-15 18:06:06 -0700302 .addAddressToTunnelInterface(
303 eq(DUMMY_RESOURCE_ID), eq(VTI_INNER_ADDRESS), anyString());
Benedict Wong76df78f2018-03-01 18:53:07 -0800304 }
Nathan Harold68a7edf2018-03-15 18:06:06 -0700305}