blob: 9bba0c0c3f06ec0606cf9ed647f7f4cc250f19b0 [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/**
72 * Set the memory which is pointed to by the Slice parameter
73 * with the content pointed to by the input Slice value.
74 */
75ACTION_TEMPLATE(SetArgSlice, HAS_1_TEMPLATE_PARAMS(int, k), AND_1_VALUE_PARAMS(value)) {
76 Slice orig = ::testing::get<k>(args);
77 android::netdutils::copy(orig, value);
78}
79
80/** Extract the content of each iovec and put it into a vector. */
81ACTION_TEMPLATE(SaveFlattenedIovecs, HAS_1_TEMPLATE_PARAMS(int, k), AND_1_VALUE_PARAMS(resVec)) {
82 std::vector<iovec> iovs = ::testing::get<k>(args);
83
84 for (const iovec& iov : iovs) {
85 resVec->insert(resVec->end(), reinterpret_cast<uint8_t*>(iov.iov_base),
86 reinterpret_cast<uint8_t*>(iov.iov_base) + iov.iov_len);
87 }
88}
89
90namespace android {
91namespace net {
92
93static constexpr int DROID_SPI = 0xD1201D;
94static constexpr size_t KEY_LENGTH = 32;
95static constexpr int NLMSG_DEFAULTSIZE = 8192;
96
97struct Policy {
98 xfrm_userpolicy_info info;
99 xfrm_user_tmpl tmpl;
100};
101
102struct NetlinkResponse {
103 nlmsghdr hdr;
104 char buf[NLMSG_DEFAULTSIZE];
105};
106
107class XfrmControllerTest : public ::testing::Test {
108public:
109 MockSyscalls mockSyscalls;
110
111 void SetUp() override { netdutils::sSyscalls.swap(mockSyscalls); }
112};
113
114TEST_F(XfrmControllerTest, TestIpSecAllocateSpi) {
115 int outSpi = 0;
116 XfrmController ctrl;
117
118 NetlinkResponse response = {};
119 response.hdr.nlmsg_type = XFRM_MSG_ALLOCSPI;
120
121 /** It's an injected return result for the sendMessage function to go through */
122 StatusOr<Slice> readStatus(netdutils::makeSlice(response));
123
124 size_t expectMsgLength = NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(xfrm_userspi_info));
125
126 // Set the return to allow the program go through
127 StatusOr<size_t> expectRet(expectMsgLength);
128
129 // A vector to hold the flattened netlink message for nlMsgSlice
130 std::vector<uint8_t> nlMsgBuf;
131 EXPECT_CALL(mockSyscalls, writev(_, _))
132 .WillOnce(DoAll(SaveFlattenedIovecs<1>(&nlMsgBuf), Return(expectRet)));
133 EXPECT_CALL(mockSyscalls, read(_, _))
134 .WillOnce(DoAll(SetArgSlice<1>(netdutils::makeSlice(response)), Return(readStatus)));
135
136 Status res = ctrl.ipSecAllocateSpi(
137 1 /* resourceId */, static_cast<int>(XfrmDirection::OUT), "127.0.0.1" /* local address */,
138 "8.8.8.8" /* remote address */, DROID_SPI /* request spi */, &outSpi);
139
140 EXPECT_EQ(0, res.code());
141 EXPECT_EQ(DROID_SPI, outSpi);
142 EXPECT_EQ(expectMsgLength, nlMsgBuf.size());
143
144 Slice nlMsgSlice = netdutils::makeSlice(nlMsgBuf);
145 nlMsgSlice = drop(nlMsgSlice, NLMSG_HDRLEN);
146
147 xfrm_userspi_info userspi{};
148 netdutils::extract(nlMsgSlice, userspi);
149
150 EXPECT_EQ(AF_INET, userspi.info.sel.family);
151
152 xfrm_address_t saddr;
153 inet_pton(AF_INET, "127.0.0.1", reinterpret_cast<void*>(&saddr));
154 EXPECT_EQ(0, memcmp(&saddr, &userspi.info.saddr, sizeof(xfrm_address_t)));
155
156 xfrm_address_t daddr;
157 inet_pton(AF_INET, "8.8.8.8", reinterpret_cast<void*>(&daddr));
158 EXPECT_EQ(0, memcmp(&daddr, &userspi.info.id.daddr, sizeof(xfrm_address_t)));
159
160 EXPECT_EQ(DROID_SPI, static_cast<int>(userspi.min));
161 EXPECT_EQ(DROID_SPI, static_cast<int>(userspi.max));
162}
163
164TEST_F(XfrmControllerTest, TestIpSecAllocateSpiIpv6) {
165 int outSpi = 0;
166 XfrmController ctrl;
167
168 NetlinkResponse response = {};
169 response.hdr.nlmsg_type = XFRM_MSG_ALLOCSPI;
170
171 /** It's an injected return result for the sendMessage function to go through */
172 StatusOr<Slice> readStatus(netdutils::makeSlice(response));
173
174 size_t expectMsgLength = NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(xfrm_userspi_info));
175 // Set the return to allow the program go through
176 StatusOr<size_t> expectRet(expectMsgLength);
177
178 // A vector to hold the flattened netlink message for nlMsgSlice
179 std::vector<uint8_t> nlMsgBuf;
180 EXPECT_CALL(mockSyscalls, writev(_, _))
181 .WillOnce(DoAll(SaveFlattenedIovecs<1>(&nlMsgBuf), Return(expectRet)));
182 EXPECT_CALL(mockSyscalls, read(_, _))
183 .WillOnce(DoAll(SetArgSlice<1>(netdutils::makeSlice(response)), Return(readStatus)));
184
185 Status res = ctrl.ipSecAllocateSpi(
186 1 /* resourceId */, static_cast<int>(XfrmDirection::OUT), "::1" /* local address */,
187 "2001:4860:4860::8888" /* remote address */, DROID_SPI /* request spi */, &outSpi);
188
189 EXPECT_EQ(0, res.code());
190 EXPECT_EQ(DROID_SPI, outSpi);
191 EXPECT_EQ(expectMsgLength, nlMsgBuf.size());
192
193 Slice nlMsgSlice = netdutils::makeSlice(nlMsgBuf);
194 nlMsgSlice = drop(nlMsgSlice, NLMSG_HDRLEN);
195
196 xfrm_userspi_info userspi{};
197 netdutils::extract(nlMsgSlice, userspi);
198
199 EXPECT_EQ(AF_INET6, userspi.info.sel.family);
200
201 xfrm_address_t saddr;
202 inet_pton(AF_INET6, "::1", reinterpret_cast<void*>(&saddr));
203 EXPECT_EQ(0, memcmp(&saddr, &userspi.info.saddr, sizeof(xfrm_address_t)));
204
205 xfrm_address_t daddr;
206 inet_pton(AF_INET6, "2001:4860:4860::8888", reinterpret_cast<void*>(&daddr));
207 EXPECT_EQ(0, memcmp(&daddr, &userspi.info.id.daddr, sizeof(xfrm_address_t)));
208
209 EXPECT_EQ(DROID_SPI, static_cast<int>(userspi.min));
210 EXPECT_EQ(DROID_SPI, static_cast<int>(userspi.max));
211}
212
213TEST_F(XfrmControllerTest, TestIpSecAddSecurityAssociation) {
214
215 int reqSpi = DROID_SPI;
216 XfrmController ctrl;
217
218 NetlinkResponse response = {};
219 response.hdr.nlmsg_type = XFRM_MSG_ALLOCSPI;
220
221 /** It's an injected return result for the sendMessage function to go through */
222 StatusOr<Slice> readStatus(netdutils::makeSlice(response));
223
224 std::vector<uint8_t> authKey(KEY_LENGTH, 0);
225 std::vector<uint8_t> cryptKey(KEY_LENGTH, 1);
226
227 // Calculate the length of the expected netlink message.
228 size_t expectMsgLength = NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(xfrm_usersa_info)) +
229 NLA_ALIGN(offsetof(XfrmController::nlattr_algo_crypt, key) + KEY_LENGTH) +
230 NLA_ALIGN(offsetof(XfrmController::nlattr_algo_auth, key) + KEY_LENGTH) +
231 NLA_ALIGN(sizeof(XfrmController::nlattr_encap_tmpl));
232 StatusOr<size_t> expectRet(expectMsgLength);
233
234 std::vector<uint8_t> nlMsgBuf;
235 EXPECT_CALL(mockSyscalls, writev(_, _))
236 .WillOnce(DoAll(SaveFlattenedIovecs<1>(&nlMsgBuf), Return(expectRet)));
237 EXPECT_CALL(mockSyscalls, read(_, _))
238 .WillOnce(DoAll(SetArgSlice<1>(netdutils::makeSlice(response)), Return(readStatus)));
239
240 Status res = ctrl.ipSecAddSecurityAssociation(
241 1 /* resourceId */, static_cast<int>(XfrmMode::TUNNEL),
242 static_cast<int>(XfrmDirection::OUT), "127.0.0.1" /* local address */,
243 "8.8.8.8" /* remote address */, 0 /* network handle */, reqSpi,
244 "hmac(sha256)" /* auth algo */, authKey, 0, "cbc(aes)" /* encryption algo */, cryptKey, 0,
245 UDP_ENCAP_ESPINUDP_NON_IKE /* encapType */, 34567 /* local port */,
246 34567 /* remote port */);
247
248 EXPECT_EQ(0, res.code());
249 EXPECT_EQ(expectMsgLength, nlMsgBuf.size());
250
251 Slice nlMsgSlice = netdutils::makeSlice(nlMsgBuf);
252 nlMsgSlice = drop(nlMsgSlice, NLMSG_HDRLEN);
253
254 xfrm_usersa_info usersa{};
255 netdutils::extract(nlMsgSlice, usersa);
256
257 EXPECT_EQ(AF_INET, usersa.family);
258 EXPECT_EQ(1 /* Transform Id*/, static_cast<int>(usersa.reqid));
259 EXPECT_EQ(XFRM_MODE_TUNNEL, usersa.mode);
260 EXPECT_EQ(htonl(DROID_SPI), usersa.id.spi);
261 EXPECT_EQ(IPPROTO_ESP, usersa.id.proto);
262
263 xfrm_address_t saddr{};
264 inet_pton(AF_INET, "127.0.0.1", reinterpret_cast<void*>(&saddr));
265 EXPECT_EQ(0, memcmp(&saddr, &usersa.saddr, sizeof(xfrm_address_t)));
266
267 xfrm_address_t daddr{};
268 inet_pton(AF_INET, "8.8.8.8", reinterpret_cast<void*>(&daddr));
269 EXPECT_EQ(0, memcmp(&daddr, &usersa.id.daddr, sizeof(xfrm_address_t)));
270
271 Slice attr_buf = drop(nlMsgSlice, NLA_ALIGN(sizeof(xfrm_usersa_info)));
272
273 // Extract and check the encryption/authentication algorithm
274 XfrmController::nlattr_algo_crypt encryptAlgo{};
275 XfrmController::nlattr_algo_auth authAlgo{};
276 auto attrHandler = [&encryptAlgo, &authAlgo](const nlattr& attr, const Slice& attr_payload) {
277 Slice buf = attr_payload;
278 if (attr.nla_type == XFRMA_ALG_CRYPT) {
279 encryptAlgo.hdr = attr;
280 netdutils::extract(buf, encryptAlgo.crypt);
281 buf = drop(buf, sizeof(xfrm_algo));
282 netdutils::extract(buf, encryptAlgo.key);
283 } else if (attr.nla_type == XFRMA_ALG_AUTH_TRUNC) {
284 authAlgo.hdr = attr;
285 netdutils::extract(buf, authAlgo.auth);
286 buf = drop(buf, sizeof(xfrm_algo_auth));
287 netdutils::extract(buf, authAlgo.key);
288 }
289 };
290 forEachNetlinkAttribute(attr_buf, attrHandler);
291
292 EXPECT_EQ(0, memcmp(reinterpret_cast<void*>(cryptKey.data()),
293 reinterpret_cast<void*>(&encryptAlgo.key), KEY_LENGTH));
294 EXPECT_EQ(0, memcmp(reinterpret_cast<void*>(authKey.data()),
295 reinterpret_cast<void*>(&authAlgo.key), KEY_LENGTH));
296}
297
298TEST_F(XfrmControllerTest, TestIpSecApplyTransportModeTransform) {
299
300 int optlen = 0;
301 const void* optval;
302 XfrmController ctrl;
303
304 struct sockaddr socketaddr;
305 socketaddr.sa_family = AF_INET;
306
307 unique_fd sock(socket(AF_INET, SOCK_STREAM, 0));
308
309 EXPECT_CALL(mockSyscalls, getsockname(_, _, _))
310 .WillOnce(DoAll(SetArgPointee<1>(socketaddr), Return(netdutils::status::ok)));
311
312 EXPECT_CALL(mockSyscalls, setsockopt(_, _, _, _, _))
313 .WillOnce(DoAll(SaveArg<3>(&optval), SaveArg<4>(&optlen), Return(netdutils::status::ok)));
314
315 Status res = ctrl.ipSecApplyTransportModeTransform(
316 sock, 1 /* resourceId */, static_cast<int>(XfrmDirection::OUT),
317 "127.0.0.1" /* local address */, "8.8.8.8" /* remote address */, DROID_SPI);
318
319 EXPECT_EQ(0, res.code());
320 EXPECT_EQ(static_cast<int>(sizeof(Policy)), optlen);
321
322 const Policy* policy = reinterpret_cast<const Policy*>(optval);
323 EXPECT_EQ(1 /* resourceId */, static_cast<int>(policy->tmpl.reqid));
324 EXPECT_EQ(htonl(DROID_SPI), policy->tmpl.id.spi);
325
326 xfrm_address_t saddr{};
327 inet_pton(AF_INET, "127.0.0.1", reinterpret_cast<void*>(&saddr));
328 EXPECT_EQ(0, memcmp(&saddr, &policy->tmpl.saddr, sizeof(xfrm_address_t)));
329
330 xfrm_address_t daddr{};
331 inet_pton(AF_INET, "8.8.8.8", reinterpret_cast<void*>(&daddr));
332 EXPECT_EQ(0, memcmp(&daddr, &policy->tmpl.id.daddr, sizeof(xfrm_address_t)));
333}
334
335TEST_F(XfrmControllerTest, TestIpSecDeleteSecurityAssociation) {
336 XfrmController ctrl;
337 NetlinkResponse response = {};
338 response.hdr.nlmsg_type = XFRM_MSG_ALLOCSPI;
339
340 /** It's an injected return result for the sendMessage function to go through */
341 StatusOr<Slice> readStatus(netdutils::makeSlice(response));
342
343 size_t expectMsgLength = NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(xfrm_usersa_id));
344 // Set the return to allow the program run through
345 StatusOr<size_t> expectRet(expectMsgLength);
346
347 std::vector<uint8_t> nlMsgBuf;
348 EXPECT_CALL(mockSyscalls, writev(_, _))
349 .WillOnce(DoAll(SaveFlattenedIovecs<1>(&nlMsgBuf), Return(expectRet)));
350 EXPECT_CALL(mockSyscalls, read(_, _))
351 .WillOnce(DoAll(SetArgSlice<1>(netdutils::makeSlice(response)), Return(readStatus)));
352
353 Status res = ctrl.ipSecDeleteSecurityAssociation(
354 1 /* resourceId */, static_cast<int>(XfrmDirection::OUT), "127.0.0.1" /* local address */,
355 "8.8.8.8" /* remote address */, DROID_SPI);
356
357 EXPECT_EQ(0, res.code());
358 EXPECT_EQ(expectMsgLength, nlMsgBuf.size());
359
360 Slice nlMsgSlice = netdutils::makeSlice(nlMsgBuf);
361 nlMsgSlice = netdutils::drop(nlMsgSlice, NLMSG_HDRLEN);
362
363 xfrm_usersa_id said{};
364 netdutils::extract(nlMsgSlice, said);
365
366 EXPECT_EQ(htonl(DROID_SPI), said.spi);
367 xfrm_address_t daddr;
368 inet_pton(AF_INET, "8.8.8.8", reinterpret_cast<void*>(&daddr));
369
370 EXPECT_EQ(0, memcmp(&daddr, &said.daddr, sizeof(xfrm_address_t)));
371}
372
373} // namespace net
374} // namespace android