blob: 7064ca92416bfa9a424054bf65adcb2739caaf79 [file] [log] [blame]
ludi5c81c762017-05-19 13:47:53 -07001/*
2 * Copyright 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 * xfrm_ctrl_test.cpp - unit tests for xfrm controllers.
17 */
18
19#include <cerrno>
20#include <cinttypes>
21#include <cstdint>
22#include <cstdio>
23#include <cstdlib>
24#include <set>
25#include <vector>
26
27#include <arpa/inet.h>
28#include <fcntl.h>
29#include <gmock/gmock.h>
30#include <ifaddrs.h>
31#include <linux/if.h>
32#include <linux/if_tun.h>
33#include <linux/netfilter/nfnetlink.h>
34#include <linux/netlink.h>
35#include <netdb.h>
36#include <netinet/in.h>
37#include <sys/socket.h>
38#include <sys/types.h>
39
40#include <android-base/macros.h>
41#include <android-base/stringprintf.h>
42#include <android-base/strings.h>
43#include <android-base/unique_fd.h>
44#include <gtest/gtest.h>
45
46#include "NetdConstants.h"
47#include "NetlinkCommands.h"
48#include "Stopwatch.h"
49#include "XfrmController.h"
50#include "android/net/INetd.h"
51#include "android/net/UidRange.h"
52#include "binder/IServiceManager.h"
53#include "netdutils/MockSyscalls.h"
54#include "netdutils/Netlink.h"
55#include "tun_interface.h"
56
57using android::base::unique_fd;
58using android::netdutils::Fd;
59using android::netdutils::MockSyscalls;
60using android::netdutils::Slice;
61using android::netdutils::Status;
62using android::netdutils::StatusOr;
63using android::netdutils::Syscalls;
64
65using ::testing::DoAll;
66using ::testing::Return;
67using ::testing::SaveArg;
68using ::testing::SetArgPointee;
69using ::testing::_;
70
71/**
Jonathan Basseric6128662017-09-14 17:32:59 -070072 * This gMock action works like SetArgPointee, but for netdutils::Slice.
73 * It sets the memory which is pointed to by the N-th argument with the supplied value.
ludi5c81c762017-05-19 13:47:53 -070074 */
Jonathan Basseric6128662017-09-14 17:32:59 -070075ACTION_TEMPLATE(SetArgSlice, HAS_1_TEMPLATE_PARAMS(int, N), AND_1_VALUE_PARAMS(value)) {
76 Slice orig = ::testing::get<N>(args);
ludi5c81c762017-05-19 13:47:53 -070077 android::netdutils::copy(orig, value);
78}
79
Jonathan Basseric6128662017-09-14 17:32:59 -070080/**
81 * This gMock action works like SaveArg, but is specialized for vector<iovec>.
82 * It copies the memory pointed to by each of the iovecs into a single vector<uint8_t>.
83 *
84 * Flattening the iovec objects cannot be done later, since there is no guarantee that the memory
85 * they point to will still be valid after the mock method returns.
86 */
87ACTION_TEMPLATE(SaveFlattenedIovecs, HAS_1_TEMPLATE_PARAMS(int, N), AND_1_VALUE_PARAMS(resVec)) {
88 const std::vector<iovec>& iovs = ::testing::get<N>(args);
ludi5c81c762017-05-19 13:47:53 -070089
90 for (const iovec& iov : iovs) {
91 resVec->insert(resVec->end(), reinterpret_cast<uint8_t*>(iov.iov_base),
92 reinterpret_cast<uint8_t*>(iov.iov_base) + iov.iov_len);
93 }
94}
95
96namespace android {
97namespace net {
98
99static constexpr int DROID_SPI = 0xD1201D;
100static constexpr size_t KEY_LENGTH = 32;
101static constexpr int NLMSG_DEFAULTSIZE = 8192;
102
103struct Policy {
104 xfrm_userpolicy_info info;
105 xfrm_user_tmpl tmpl;
106};
107
108struct NetlinkResponse {
109 nlmsghdr hdr;
110 char buf[NLMSG_DEFAULTSIZE];
111};
112
113class XfrmControllerTest : public ::testing::Test {
114public:
115 MockSyscalls mockSyscalls;
116
117 void SetUp() override { netdutils::sSyscalls.swap(mockSyscalls); }
118};
119
120TEST_F(XfrmControllerTest, TestIpSecAllocateSpi) {
121 int outSpi = 0;
122 XfrmController ctrl;
123
124 NetlinkResponse response = {};
125 response.hdr.nlmsg_type = XFRM_MSG_ALLOCSPI;
126
127 /** It's an injected return result for the sendMessage function to go through */
128 StatusOr<Slice> readStatus(netdutils::makeSlice(response));
129
130 size_t expectMsgLength = NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(xfrm_userspi_info));
131
132 // Set the return to allow the program go through
133 StatusOr<size_t> expectRet(expectMsgLength);
134
135 // A vector to hold the flattened netlink message for nlMsgSlice
136 std::vector<uint8_t> nlMsgBuf;
137 EXPECT_CALL(mockSyscalls, writev(_, _))
138 .WillOnce(DoAll(SaveFlattenedIovecs<1>(&nlMsgBuf), Return(expectRet)));
139 EXPECT_CALL(mockSyscalls, read(_, _))
140 .WillOnce(DoAll(SetArgSlice<1>(netdutils::makeSlice(response)), Return(readStatus)));
141
142 Status res = ctrl.ipSecAllocateSpi(
143 1 /* resourceId */, static_cast<int>(XfrmDirection::OUT), "127.0.0.1" /* local address */,
144 "8.8.8.8" /* remote address */, DROID_SPI /* request spi */, &outSpi);
145
146 EXPECT_EQ(0, res.code());
147 EXPECT_EQ(DROID_SPI, outSpi);
148 EXPECT_EQ(expectMsgLength, nlMsgBuf.size());
149
150 Slice nlMsgSlice = netdutils::makeSlice(nlMsgBuf);
151 nlMsgSlice = drop(nlMsgSlice, NLMSG_HDRLEN);
152
153 xfrm_userspi_info userspi{};
154 netdutils::extract(nlMsgSlice, userspi);
155
156 EXPECT_EQ(AF_INET, userspi.info.sel.family);
157
158 xfrm_address_t saddr;
159 inet_pton(AF_INET, "127.0.0.1", reinterpret_cast<void*>(&saddr));
160 EXPECT_EQ(0, memcmp(&saddr, &userspi.info.saddr, sizeof(xfrm_address_t)));
161
162 xfrm_address_t daddr;
163 inet_pton(AF_INET, "8.8.8.8", reinterpret_cast<void*>(&daddr));
164 EXPECT_EQ(0, memcmp(&daddr, &userspi.info.id.daddr, sizeof(xfrm_address_t)));
165
166 EXPECT_EQ(DROID_SPI, static_cast<int>(userspi.min));
167 EXPECT_EQ(DROID_SPI, static_cast<int>(userspi.max));
168}
169
170TEST_F(XfrmControllerTest, TestIpSecAllocateSpiIpv6) {
171 int outSpi = 0;
172 XfrmController ctrl;
173
174 NetlinkResponse response = {};
175 response.hdr.nlmsg_type = XFRM_MSG_ALLOCSPI;
176
177 /** It's an injected return result for the sendMessage function to go through */
178 StatusOr<Slice> readStatus(netdutils::makeSlice(response));
179
180 size_t expectMsgLength = NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(xfrm_userspi_info));
181 // Set the return to allow the program go through
182 StatusOr<size_t> expectRet(expectMsgLength);
183
184 // A vector to hold the flattened netlink message for nlMsgSlice
185 std::vector<uint8_t> nlMsgBuf;
186 EXPECT_CALL(mockSyscalls, writev(_, _))
187 .WillOnce(DoAll(SaveFlattenedIovecs<1>(&nlMsgBuf), Return(expectRet)));
188 EXPECT_CALL(mockSyscalls, read(_, _))
189 .WillOnce(DoAll(SetArgSlice<1>(netdutils::makeSlice(response)), Return(readStatus)));
190
191 Status res = ctrl.ipSecAllocateSpi(
192 1 /* resourceId */, static_cast<int>(XfrmDirection::OUT), "::1" /* local address */,
193 "2001:4860:4860::8888" /* remote address */, DROID_SPI /* request spi */, &outSpi);
194
195 EXPECT_EQ(0, res.code());
196 EXPECT_EQ(DROID_SPI, outSpi);
197 EXPECT_EQ(expectMsgLength, nlMsgBuf.size());
198
199 Slice nlMsgSlice = netdutils::makeSlice(nlMsgBuf);
200 nlMsgSlice = drop(nlMsgSlice, NLMSG_HDRLEN);
201
202 xfrm_userspi_info userspi{};
203 netdutils::extract(nlMsgSlice, userspi);
204
205 EXPECT_EQ(AF_INET6, userspi.info.sel.family);
206
207 xfrm_address_t saddr;
208 inet_pton(AF_INET6, "::1", reinterpret_cast<void*>(&saddr));
209 EXPECT_EQ(0, memcmp(&saddr, &userspi.info.saddr, sizeof(xfrm_address_t)));
210
211 xfrm_address_t daddr;
212 inet_pton(AF_INET6, "2001:4860:4860::8888", reinterpret_cast<void*>(&daddr));
213 EXPECT_EQ(0, memcmp(&daddr, &userspi.info.id.daddr, sizeof(xfrm_address_t)));
214
215 EXPECT_EQ(DROID_SPI, static_cast<int>(userspi.min));
216 EXPECT_EQ(DROID_SPI, static_cast<int>(userspi.max));
217}
218
219TEST_F(XfrmControllerTest, TestIpSecAddSecurityAssociation) {
220
221 int reqSpi = DROID_SPI;
222 XfrmController ctrl;
223
224 NetlinkResponse response = {};
225 response.hdr.nlmsg_type = XFRM_MSG_ALLOCSPI;
226
227 /** It's an injected return result for the sendMessage function to go through */
228 StatusOr<Slice> readStatus(netdutils::makeSlice(response));
229
230 std::vector<uint8_t> authKey(KEY_LENGTH, 0);
231 std::vector<uint8_t> cryptKey(KEY_LENGTH, 1);
232
233 // Calculate the length of the expected netlink message.
234 size_t expectMsgLength = NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(xfrm_usersa_info)) +
235 NLA_ALIGN(offsetof(XfrmController::nlattr_algo_crypt, key) + KEY_LENGTH) +
236 NLA_ALIGN(offsetof(XfrmController::nlattr_algo_auth, key) + KEY_LENGTH) +
237 NLA_ALIGN(sizeof(XfrmController::nlattr_encap_tmpl));
238 StatusOr<size_t> expectRet(expectMsgLength);
239
240 std::vector<uint8_t> nlMsgBuf;
241 EXPECT_CALL(mockSyscalls, writev(_, _))
242 .WillOnce(DoAll(SaveFlattenedIovecs<1>(&nlMsgBuf), Return(expectRet)));
243 EXPECT_CALL(mockSyscalls, read(_, _))
244 .WillOnce(DoAll(SetArgSlice<1>(netdutils::makeSlice(response)), Return(readStatus)));
245
246 Status res = ctrl.ipSecAddSecurityAssociation(
247 1 /* resourceId */, static_cast<int>(XfrmMode::TUNNEL),
248 static_cast<int>(XfrmDirection::OUT), "127.0.0.1" /* local address */,
249 "8.8.8.8" /* remote address */, 0 /* network handle */, reqSpi,
250 "hmac(sha256)" /* auth algo */, authKey, 0, "cbc(aes)" /* encryption algo */, cryptKey, 0,
251 UDP_ENCAP_ESPINUDP_NON_IKE /* encapType */, 34567 /* local port */,
252 34567 /* remote port */);
253
254 EXPECT_EQ(0, res.code());
255 EXPECT_EQ(expectMsgLength, nlMsgBuf.size());
256
257 Slice nlMsgSlice = netdutils::makeSlice(nlMsgBuf);
258 nlMsgSlice = drop(nlMsgSlice, NLMSG_HDRLEN);
259
260 xfrm_usersa_info usersa{};
261 netdutils::extract(nlMsgSlice, usersa);
262
263 EXPECT_EQ(AF_INET, usersa.family);
264 EXPECT_EQ(1 /* Transform Id*/, static_cast<int>(usersa.reqid));
265 EXPECT_EQ(XFRM_MODE_TUNNEL, usersa.mode);
266 EXPECT_EQ(htonl(DROID_SPI), usersa.id.spi);
267 EXPECT_EQ(IPPROTO_ESP, usersa.id.proto);
268
269 xfrm_address_t saddr{};
270 inet_pton(AF_INET, "127.0.0.1", reinterpret_cast<void*>(&saddr));
271 EXPECT_EQ(0, memcmp(&saddr, &usersa.saddr, sizeof(xfrm_address_t)));
272
273 xfrm_address_t daddr{};
274 inet_pton(AF_INET, "8.8.8.8", reinterpret_cast<void*>(&daddr));
275 EXPECT_EQ(0, memcmp(&daddr, &usersa.id.daddr, sizeof(xfrm_address_t)));
276
277 Slice attr_buf = drop(nlMsgSlice, NLA_ALIGN(sizeof(xfrm_usersa_info)));
278
279 // Extract and check the encryption/authentication algorithm
280 XfrmController::nlattr_algo_crypt encryptAlgo{};
281 XfrmController::nlattr_algo_auth authAlgo{};
282 auto attrHandler = [&encryptAlgo, &authAlgo](const nlattr& attr, const Slice& attr_payload) {
283 Slice buf = attr_payload;
284 if (attr.nla_type == XFRMA_ALG_CRYPT) {
285 encryptAlgo.hdr = attr;
286 netdutils::extract(buf, encryptAlgo.crypt);
287 buf = drop(buf, sizeof(xfrm_algo));
288 netdutils::extract(buf, encryptAlgo.key);
289 } else if (attr.nla_type == XFRMA_ALG_AUTH_TRUNC) {
290 authAlgo.hdr = attr;
291 netdutils::extract(buf, authAlgo.auth);
292 buf = drop(buf, sizeof(xfrm_algo_auth));
293 netdutils::extract(buf, authAlgo.key);
294 }
295 };
296 forEachNetlinkAttribute(attr_buf, attrHandler);
297
298 EXPECT_EQ(0, memcmp(reinterpret_cast<void*>(cryptKey.data()),
299 reinterpret_cast<void*>(&encryptAlgo.key), KEY_LENGTH));
300 EXPECT_EQ(0, memcmp(reinterpret_cast<void*>(authKey.data()),
301 reinterpret_cast<void*>(&authAlgo.key), KEY_LENGTH));
302}
303
304TEST_F(XfrmControllerTest, TestIpSecApplyTransportModeTransform) {
305
306 int optlen = 0;
307 const void* optval;
308 XfrmController ctrl;
309
310 struct sockaddr socketaddr;
311 socketaddr.sa_family = AF_INET;
312
313 unique_fd sock(socket(AF_INET, SOCK_STREAM, 0));
314
315 EXPECT_CALL(mockSyscalls, getsockname(_, _, _))
316 .WillOnce(DoAll(SetArgPointee<1>(socketaddr), Return(netdutils::status::ok)));
317
318 EXPECT_CALL(mockSyscalls, setsockopt(_, _, _, _, _))
319 .WillOnce(DoAll(SaveArg<3>(&optval), SaveArg<4>(&optlen), Return(netdutils::status::ok)));
320
321 Status res = ctrl.ipSecApplyTransportModeTransform(
322 sock, 1 /* resourceId */, static_cast<int>(XfrmDirection::OUT),
323 "127.0.0.1" /* local address */, "8.8.8.8" /* remote address */, DROID_SPI);
324
325 EXPECT_EQ(0, res.code());
326 EXPECT_EQ(static_cast<int>(sizeof(Policy)), optlen);
327
328 const Policy* policy = reinterpret_cast<const Policy*>(optval);
329 EXPECT_EQ(1 /* resourceId */, static_cast<int>(policy->tmpl.reqid));
330 EXPECT_EQ(htonl(DROID_SPI), policy->tmpl.id.spi);
331
332 xfrm_address_t saddr{};
333 inet_pton(AF_INET, "127.0.0.1", reinterpret_cast<void*>(&saddr));
334 EXPECT_EQ(0, memcmp(&saddr, &policy->tmpl.saddr, sizeof(xfrm_address_t)));
335
336 xfrm_address_t daddr{};
337 inet_pton(AF_INET, "8.8.8.8", reinterpret_cast<void*>(&daddr));
338 EXPECT_EQ(0, memcmp(&daddr, &policy->tmpl.id.daddr, sizeof(xfrm_address_t)));
339}
340
341TEST_F(XfrmControllerTest, TestIpSecDeleteSecurityAssociation) {
342 XfrmController ctrl;
343 NetlinkResponse response = {};
344 response.hdr.nlmsg_type = XFRM_MSG_ALLOCSPI;
345
346 /** It's an injected return result for the sendMessage function to go through */
347 StatusOr<Slice> readStatus(netdutils::makeSlice(response));
348
349 size_t expectMsgLength = NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(xfrm_usersa_id));
350 // Set the return to allow the program run through
351 StatusOr<size_t> expectRet(expectMsgLength);
352
353 std::vector<uint8_t> nlMsgBuf;
354 EXPECT_CALL(mockSyscalls, writev(_, _))
355 .WillOnce(DoAll(SaveFlattenedIovecs<1>(&nlMsgBuf), Return(expectRet)));
356 EXPECT_CALL(mockSyscalls, read(_, _))
357 .WillOnce(DoAll(SetArgSlice<1>(netdutils::makeSlice(response)), Return(readStatus)));
358
359 Status res = ctrl.ipSecDeleteSecurityAssociation(
360 1 /* resourceId */, static_cast<int>(XfrmDirection::OUT), "127.0.0.1" /* local address */,
361 "8.8.8.8" /* remote address */, DROID_SPI);
362
363 EXPECT_EQ(0, res.code());
364 EXPECT_EQ(expectMsgLength, nlMsgBuf.size());
365
366 Slice nlMsgSlice = netdutils::makeSlice(nlMsgBuf);
367 nlMsgSlice = netdutils::drop(nlMsgSlice, NLMSG_HDRLEN);
368
369 xfrm_usersa_id said{};
370 netdutils::extract(nlMsgSlice, said);
371
372 EXPECT_EQ(htonl(DROID_SPI), said.spi);
373 xfrm_address_t daddr;
374 inet_pton(AF_INET, "8.8.8.8", reinterpret_cast<void*>(&daddr));
375
376 EXPECT_EQ(0, memcmp(&daddr, &said.daddr, sizeof(xfrm_address_t)));
377}
378
379} // namespace net
380} // namespace android