blob: 730e2d56bd780b35097188bab3948ee9b2ca3aae [file] [log] [blame]
Remi NGUYEN VAN678277c2021-05-11 13:37:06 +00001/*
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;
22
23import 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
34import android.system.Os;
35import android.test.mock.MockContext;
36
37import androidx.test.filters.SmallTest;
38import androidx.test.runner.AndroidJUnit4;
39
40import com.android.server.IpSecService;
41
42import org.junit.Before;
43import org.junit.Test;
44import org.junit.runner.RunWith;
45
46import java.net.InetAddress;
47import java.net.Socket;
48import java.net.UnknownHostException;
49
50/** Unit tests for {@link IpSecManager}. */
51@SmallTest
52@RunWith(AndroidJUnit4.class)
53public class IpSecManagerTest {
54
55 private static final int TEST_UDP_ENCAP_PORT = 34567;
56 private static final int DROID_SPI = 0xD1201D;
57 private static final int DUMMY_RESOURCE_ID = 0x1234;
58
59 private static final InetAddress GOOGLE_DNS_4;
60 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");
63
64 static {
65 try {
66 // Google Public DNS Addresses;
67 GOOGLE_DNS_4 = InetAddress.getByName("8.8.8.8");
68 VTI_LOCAL_ADDRESS = InetAddress.getByName("8.8.4.4");
69 } catch (UnknownHostException e) {
70 throw new RuntimeException("Could not resolve DNS Addresses", e);
71 }
72 }
73
74 private IpSecService mMockIpSecService;
75 private IpSecManager mIpSecManager;
76 private MockContext mMockContext = new MockContext() {
77 @Override
78 public String getOpPackageName() {
79 return "fooPackage";
80 }
81 };
82
83 @Before
84 public void setUp() throws Exception {
85 mMockIpSecService = mock(IpSecService.class);
86 mIpSecManager = new IpSecManager(mMockContext, mMockIpSecService);
87 }
88
89 /*
90 * Allocate a specific SPI
91 * Close SPIs
92 */
93 @Test
94 public void testAllocSpi() throws Exception {
95 IpSecSpiResponse spiResp =
96 new IpSecSpiResponse(IpSecManager.Status.OK, DUMMY_RESOURCE_ID, DROID_SPI);
97 when(mMockIpSecService.allocateSecurityParameterIndex(
98 eq(GOOGLE_DNS_4.getHostAddress()),
99 eq(DROID_SPI),
100 anyObject()))
101 .thenReturn(spiResp);
102
103 IpSecManager.SecurityParameterIndex droidSpi =
104 mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4, DROID_SPI);
105 assertEquals(DROID_SPI, droidSpi.getSpi());
106
107 droidSpi.close();
108
109 verify(mMockIpSecService).releaseSecurityParameterIndex(DUMMY_RESOURCE_ID);
110 }
111
112 @Test
113 public void testAllocRandomSpi() throws Exception {
114 IpSecSpiResponse spiResp =
115 new IpSecSpiResponse(IpSecManager.Status.OK, DUMMY_RESOURCE_ID, DROID_SPI);
116 when(mMockIpSecService.allocateSecurityParameterIndex(
117 eq(GOOGLE_DNS_4.getHostAddress()),
118 eq(IpSecManager.INVALID_SECURITY_PARAMETER_INDEX),
119 anyObject()))
120 .thenReturn(spiResp);
121
122 IpSecManager.SecurityParameterIndex randomSpi =
123 mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4);
124
125 assertEquals(DROID_SPI, randomSpi.getSpi());
126
127 randomSpi.close();
128
129 verify(mMockIpSecService).releaseSecurityParameterIndex(DUMMY_RESOURCE_ID);
130 }
131
132 /*
133 * Throws resource unavailable exception
134 */
135 @Test
136 public void testAllocSpiResUnavailableException() throws Exception {
137 IpSecSpiResponse spiResp =
138 new IpSecSpiResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE, 0, 0);
139 when(mMockIpSecService.allocateSecurityParameterIndex(
140 anyString(), anyInt(), anyObject()))
141 .thenReturn(spiResp);
142
143 try {
144 mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4);
145 fail("ResourceUnavailableException was not thrown");
146 } catch (IpSecManager.ResourceUnavailableException e) {
147 }
148 }
149
150 /*
151 * Throws spi unavailable exception
152 */
153 @Test
154 public void testAllocSpiSpiUnavailableException() throws Exception {
155 IpSecSpiResponse spiResp = new IpSecSpiResponse(IpSecManager.Status.SPI_UNAVAILABLE, 0, 0);
156 when(mMockIpSecService.allocateSecurityParameterIndex(
157 anyString(), anyInt(), anyObject()))
158 .thenReturn(spiResp);
159
160 try {
161 mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4);
162 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 {
173 mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4, 0);
174 fail("Able to allocate invalid spi");
175 } catch (IllegalArgumentException e) {
176 }
177 }
178
179 @Test
180 public void testOpenEncapsulationSocket() throws Exception {
181 IpSecUdpEncapResponse udpEncapResp =
182 new IpSecUdpEncapResponse(
183 IpSecManager.Status.OK,
184 DUMMY_RESOURCE_ID,
185 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);
192 assertNotNull(encapSocket.getFileDescriptor());
193 assertEquals(TEST_UDP_ENCAP_PORT, encapSocket.getPort());
194
195 encapSocket.close();
196
197 verify(mMockIpSecService).closeUdpEncapsulationSocket(DUMMY_RESOURCE_ID);
198 }
199
200 @Test
201 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
228 public void testOpenEncapsulationSocketOnRandomPort() throws Exception {
229 IpSecUdpEncapResponse udpEncapResp =
230 new IpSecUdpEncapResponse(
231 IpSecManager.Status.OK,
232 DUMMY_RESOURCE_ID,
233 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
242 assertNotNull(encapSocket.getFileDescriptor());
243 assertEquals(TEST_UDP_ENCAP_PORT, encapSocket.getPort());
244
245 encapSocket.close();
246
247 verify(mMockIpSecService).closeUdpEncapsulationSocket(DUMMY_RESOURCE_ID);
248 }
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
260
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()),
267 anyObject(), anyObject(), anyString()))
268 .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();
285 verify(mMockIpSecService).deleteTunnelInterface(eq(DUMMY_RESOURCE_ID), anyString());
286 }
287
288 @Test
289 public void testAddRemoveAddressesFromVti() throws Exception {
290 IpSecManager.IpSecTunnelInterface tunnelIntf =
291 createAndValidateVti(DUMMY_RESOURCE_ID, VTI_INTF_NAME);
292
293 tunnelIntf.addAddress(VTI_INNER_ADDRESS.getAddress(),
294 VTI_INNER_ADDRESS.getPrefixLength());
295 verify(mMockIpSecService)
296 .addAddressToTunnelInterface(
297 eq(DUMMY_RESOURCE_ID), eq(VTI_INNER_ADDRESS), anyString());
298
299 tunnelIntf.removeAddress(VTI_INNER_ADDRESS.getAddress(),
300 VTI_INNER_ADDRESS.getPrefixLength());
301 verify(mMockIpSecService)
302 .addAddressToTunnelInterface(
303 eq(DUMMY_RESOURCE_ID), eq(VTI_INNER_ADDRESS), anyString());
304 }
305}