blob: 2a2382f3e86fe676bdade56f4b0aaa729e4a65b8 [file] [log] [blame]
Nathan Harold1a371532017-01-30 12:30:48 -08001/*
2 *
3 * Copyright (C) 2017 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
Nathan Harold1e284452017-10-10 13:31:19 -070018#include <random>
Nathan Harold7441c692017-12-12 21:25:01 -080019#include <string>
Nathan Harold1a371532017-01-30 12:30:48 -080020#include <vector>
21
22#include <ctype.h>
23#include <errno.h>
24#include <fcntl.h>
25#include <getopt.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
Nathan Harold420ceac2017-04-05 19:36:59 -070029
30#define __STDC_FORMAT_MACROS
Nathan Harold1a371532017-01-30 12:30:48 -080031#include <inttypes.h>
32
33#include <arpa/inet.h>
34#include <netinet/in.h>
35
36#include <sys/socket.h>
37#include <sys/stat.h>
38#include <sys/types.h>
39#include <sys/wait.h>
40
41#include <linux/in.h>
Nathan Harold21299f72018-03-16 20:13:03 -070042#include <linux/ipsec.h>
Nathan Harold1a371532017-01-30 12:30:48 -080043#include <linux/netlink.h>
44#include <linux/xfrm.h>
45
Nathan Harold45c35662018-04-23 10:10:18 -070046#define LOG_TAG "XfrmController"
Nathan Harold1a371532017-01-30 12:30:48 -080047#include "android-base/stringprintf.h"
48#include "android-base/strings.h"
49#include "android-base/unique_fd.h"
Nathan Harold45c35662018-04-23 10:10:18 -070050#include <android/net/INetd.h>
Manojd9c93c22017-10-19 13:40:26 -070051#include <log/log_properties.h>
Nathan Harold21299f72018-03-16 20:13:03 -070052#include "InterfaceController.h"
Nathan Harold1a371532017-01-30 12:30:48 -080053#include "NetdConstants.h"
54#include "NetlinkCommands.h"
55#include "ResponseCode.h"
56#include "XfrmController.h"
ludi4072ff22017-06-15 08:56:52 -070057#include "netdutils/Fd.h"
58#include "netdutils/Slice.h"
59#include "netdutils/Syscalls.h"
Nathan Harold1a371532017-01-30 12:30:48 -080060#include <cutils/properties.h>
Logan Chien3f461482018-04-23 14:31:32 +080061#include <log/log.h>
Nathan Harold1a371532017-01-30 12:30:48 -080062#include <logwrap/logwrap.h>
63
Nathan Harold45c35662018-04-23 10:10:18 -070064using android::net::INetd;
ludi4072ff22017-06-15 08:56:52 -070065using android::netdutils::Fd;
66using android::netdutils::Slice;
67using android::netdutils::Status;
68using android::netdutils::StatusOr;
69using android::netdutils::Syscalls;
70
Nathan Harold1a371532017-01-30 12:30:48 -080071namespace android {
72namespace net {
73
Nathan Harold39b5df42017-08-02 18:45:25 -070074// Exposed for testing
Nathan Harold1a371532017-01-30 12:30:48 -080075constexpr uint32_t ALGO_MASK_AUTH_ALL = ~0;
Nathan Harold39b5df42017-08-02 18:45:25 -070076// Exposed for testing
Nathan Harold1a371532017-01-30 12:30:48 -080077constexpr uint32_t ALGO_MASK_CRYPT_ALL = ~0;
Nathan Harold39b5df42017-08-02 18:45:25 -070078// Exposed for testing
Benedict Wongbe65b432017-08-22 21:43:14 -070079constexpr uint32_t ALGO_MASK_AEAD_ALL = ~0;
80// Exposed for testing
Nathan Harold1a371532017-01-30 12:30:48 -080081constexpr uint8_t REPLAY_WINDOW_SIZE = 4;
82
Nathan Harold39b5df42017-08-02 18:45:25 -070083namespace {
84
Nathan Harold1012ffe2018-03-28 08:59:24 -070085constexpr uint32_t RAND_SPI_MIN = 256;
Nathan Harold1a371532017-01-30 12:30:48 -080086constexpr uint32_t RAND_SPI_MAX = 0xFFFFFFFE;
87
88constexpr uint32_t INVALID_SPI = 0;
89
90#define XFRM_MSG_TRANS(x) \
91 case x: \
92 return #x;
93
94const char* xfrmMsgTypeToString(uint16_t msg) {
95 switch (msg) {
96 XFRM_MSG_TRANS(XFRM_MSG_NEWSA)
97 XFRM_MSG_TRANS(XFRM_MSG_DELSA)
98 XFRM_MSG_TRANS(XFRM_MSG_GETSA)
99 XFRM_MSG_TRANS(XFRM_MSG_NEWPOLICY)
100 XFRM_MSG_TRANS(XFRM_MSG_DELPOLICY)
101 XFRM_MSG_TRANS(XFRM_MSG_GETPOLICY)
102 XFRM_MSG_TRANS(XFRM_MSG_ALLOCSPI)
103 XFRM_MSG_TRANS(XFRM_MSG_ACQUIRE)
104 XFRM_MSG_TRANS(XFRM_MSG_EXPIRE)
105 XFRM_MSG_TRANS(XFRM_MSG_UPDPOLICY)
106 XFRM_MSG_TRANS(XFRM_MSG_UPDSA)
107 XFRM_MSG_TRANS(XFRM_MSG_POLEXPIRE)
108 XFRM_MSG_TRANS(XFRM_MSG_FLUSHSA)
109 XFRM_MSG_TRANS(XFRM_MSG_FLUSHPOLICY)
110 XFRM_MSG_TRANS(XFRM_MSG_NEWAE)
111 XFRM_MSG_TRANS(XFRM_MSG_GETAE)
112 XFRM_MSG_TRANS(XFRM_MSG_REPORT)
113 XFRM_MSG_TRANS(XFRM_MSG_MIGRATE)
114 XFRM_MSG_TRANS(XFRM_MSG_NEWSADINFO)
115 XFRM_MSG_TRANS(XFRM_MSG_GETSADINFO)
116 XFRM_MSG_TRANS(XFRM_MSG_GETSPDINFO)
117 XFRM_MSG_TRANS(XFRM_MSG_NEWSPDINFO)
118 XFRM_MSG_TRANS(XFRM_MSG_MAPPING)
119 default:
120 return "XFRM_MSG UNKNOWN";
121 }
122}
123
124// actually const but cannot be declared as such for reasons
125uint8_t kPadBytesArray[] = {0, 0, 0};
126void* kPadBytes = static_cast<void*>(kPadBytesArray);
127
Nathan Harold420ceac2017-04-05 19:36:59 -0700128#define LOG_HEX(__desc16__, __buf__, __len__) \
Manojd9c93c22017-10-19 13:40:26 -0700129 if (__android_log_is_debuggable()) { \
130 do { \
131 logHex(__desc16__, __buf__, __len__); \
Nathan Harold7441c692017-12-12 21:25:01 -0800132 } while (0); \
Manojd9c93c22017-10-19 13:40:26 -0700133 }
134
ludie51e3862017-08-15 19:28:12 -0700135#define LOG_IOV(__iov__) \
Manojd9c93c22017-10-19 13:40:26 -0700136 if (__android_log_is_debuggable()) { \
137 do { \
138 logIov(__iov__); \
Nathan Harold7441c692017-12-12 21:25:01 -0800139 } while (0); \
140 }
Nathan Harold1a371532017-01-30 12:30:48 -0800141
142void logHex(const char* desc16, const char* buf, size_t len) {
143 char* printBuf = new char[len * 2 + 1 + 26]; // len->ascii, +newline, +prefix strlen
144 int offset = 0;
145 if (desc16) {
146 sprintf(printBuf, "{%-16s}", desc16);
147 offset += 18; // prefix string length
148 }
149 sprintf(printBuf + offset, "[%4.4u]: ", (len > 9999) ? 9999 : (unsigned)len);
150 offset += 8;
151
152 for (uint32_t j = 0; j < (uint32_t)len; j++) {
Wolloh Chou4d1e5c72018-03-22 15:14:33 +0800153 sprintf(&printBuf[j * 2 + offset], "%0.2x", (unsigned char)buf[j]);
Nathan Harold1a371532017-01-30 12:30:48 -0800154 }
155 ALOGD("%s", printBuf);
156 delete[] printBuf;
157}
158
ludie51e3862017-08-15 19:28:12 -0700159void logIov(const std::vector<iovec>& iov) {
160 for (const iovec& row : iov) {
161 logHex(0, reinterpret_cast<char*>(row.iov_base), row.iov_len);
Nathan Harold1a371532017-01-30 12:30:48 -0800162 }
163}
164
manojboopathi8707f232018-01-02 14:45:47 -0800165size_t fillNlAttr(__u16 nlaType, size_t valueSize, nlattr* nlAttr) {
166 size_t dataLen = valueSize;
167 int padLength = NLMSG_ALIGN(dataLen) - dataLen;
168 nlAttr->nla_len = (__u16)(dataLen + sizeof(nlattr));
169 nlAttr->nla_type = nlaType;
170 return padLength;
171}
172
173size_t fillNlAttrIpAddress(__u16 nlaType, int family, const std::string& value, nlattr* nlAttr,
174 Slice ipAddress) {
175 inet_pton(family, value.c_str(), ipAddress.base());
176 return fillNlAttr(nlaType, (family == AF_INET) ? sizeof(in_addr) : sizeof(in6_addr), nlAttr);
177}
178
179size_t fillNlAttrU32(__u16 nlaType, int32_t value, nlattr* nlAttr, uint32_t* u32Value) {
180 *u32Value = htonl(value);
181 return fillNlAttr(nlaType, sizeof((*u32Value)), nlAttr);
182}
183
184// returns the address family, placing the string in the provided buffer
185StatusOr<uint16_t> convertStringAddress(std::string addr, uint8_t* buffer) {
186 if (inet_pton(AF_INET, addr.c_str(), buffer) == 1) {
187 return AF_INET;
188 } else if (inet_pton(AF_INET6, addr.c_str(), buffer) == 1) {
189 return AF_INET6;
190 } else {
191 return Status(EAFNOSUPPORT);
192 }
193}
194
ludi6e8eccd2017-08-14 14:40:37 -0700195// TODO: Need to consider a way to refer to the sSycalls instance
ludi4072ff22017-06-15 08:56:52 -0700196inline Syscalls& getSyscallInstance() { return netdutils::sSyscalls.get(); }
197
Nathan Harold1a371532017-01-30 12:30:48 -0800198class XfrmSocketImpl : public XfrmSocket {
199private:
200 static constexpr int NLMSG_DEFAULTSIZE = 8192;
201
202 union NetlinkResponse {
203 nlmsghdr hdr;
204 struct _err_ {
205 nlmsghdr hdr;
206 nlmsgerr err;
207 } err;
208
209 struct _buf_ {
210 nlmsghdr hdr;
211 char buf[NLMSG_DEFAULTSIZE];
212 } buf;
213 };
214
215public:
ludi6e8eccd2017-08-14 14:40:37 -0700216 netdutils::Status open() override {
Nathan Harold1a371532017-01-30 12:30:48 -0800217 mSock = openNetlinkSocket(NETLINK_XFRM);
ludi6e8eccd2017-08-14 14:40:37 -0700218 if (mSock < 0) {
Nathan Harold1a371532017-01-30 12:30:48 -0800219 ALOGW("Could not get a new socket, line=%d", __LINE__);
ludi6e8eccd2017-08-14 14:40:37 -0700220 return netdutils::statusFromErrno(-mSock, "Could not open netlink socket");
Nathan Harold1a371532017-01-30 12:30:48 -0800221 }
222
ludi6e8eccd2017-08-14 14:40:37 -0700223 return netdutils::status::ok;
Nathan Harold1a371532017-01-30 12:30:48 -0800224 }
225
ludi6e8eccd2017-08-14 14:40:37 -0700226 static netdutils::Status validateResponse(NetlinkResponse response, size_t len) {
Nathan Harold1a371532017-01-30 12:30:48 -0800227 if (len < sizeof(nlmsghdr)) {
228 ALOGW("Invalid response message received over netlink");
ludi6e8eccd2017-08-14 14:40:37 -0700229 return netdutils::statusFromErrno(EBADMSG, "Invalid message");
Nathan Harold1a371532017-01-30 12:30:48 -0800230 }
231
232 switch (response.hdr.nlmsg_type) {
233 case NLMSG_NOOP:
234 case NLMSG_DONE:
ludi6e8eccd2017-08-14 14:40:37 -0700235 return netdutils::status::ok;
Nathan Harold1a371532017-01-30 12:30:48 -0800236 case NLMSG_OVERRUN:
237 ALOGD("Netlink request overran kernel buffer");
ludi6e8eccd2017-08-14 14:40:37 -0700238 return netdutils::statusFromErrno(EBADMSG, "Kernel buffer overrun");
Nathan Harold1a371532017-01-30 12:30:48 -0800239 case NLMSG_ERROR:
240 if (len < sizeof(NetlinkResponse::_err_)) {
241 ALOGD("Netlink message received malformed error response");
ludi6e8eccd2017-08-14 14:40:37 -0700242 return netdutils::statusFromErrno(EBADMSG, "Malformed error response");
Nathan Harold1a371532017-01-30 12:30:48 -0800243 }
ludi6e8eccd2017-08-14 14:40:37 -0700244 return netdutils::statusFromErrno(
245 -response.err.err.error,
246 "Error netlink message"); // Netlink errors are negative errno.
Nathan Harold1a371532017-01-30 12:30:48 -0800247 case XFRM_MSG_NEWSA:
248 break;
249 }
250
251 if (response.hdr.nlmsg_type < XFRM_MSG_BASE /*== NLMSG_MIN_TYPE*/ ||
252 response.hdr.nlmsg_type > XFRM_MSG_MAX) {
253 ALOGD("Netlink message responded with an out-of-range message ID");
ludi6e8eccd2017-08-14 14:40:37 -0700254 return netdutils::statusFromErrno(EBADMSG, "Invalid message ID");
Nathan Harold1a371532017-01-30 12:30:48 -0800255 }
256
257 // TODO Add more message validation here
ludi6e8eccd2017-08-14 14:40:37 -0700258 return netdutils::status::ok;
Nathan Harold1a371532017-01-30 12:30:48 -0800259 }
260
ludi6e8eccd2017-08-14 14:40:37 -0700261 netdutils::Status sendMessage(uint16_t nlMsgType, uint16_t nlMsgFlags, uint16_t nlMsgSeqNum,
262 std::vector<iovec>* iovecs) const override {
Nathan Harold1a371532017-01-30 12:30:48 -0800263 nlmsghdr nlMsg = {
Nathan Harold7441c692017-12-12 21:25:01 -0800264 .nlmsg_type = nlMsgType,
265 .nlmsg_flags = nlMsgFlags,
266 .nlmsg_seq = nlMsgSeqNum,
Nathan Harold1a371532017-01-30 12:30:48 -0800267 };
268
ludie51e3862017-08-15 19:28:12 -0700269 (*iovecs)[0].iov_base = &nlMsg;
270 (*iovecs)[0].iov_len = NLMSG_HDRLEN;
271 for (const iovec& iov : *iovecs) {
272 nlMsg.nlmsg_len += iov.iov_len;
Nathan Harold1a371532017-01-30 12:30:48 -0800273 }
274
275 ALOGD("Sending Netlink XFRM Message: %s", xfrmMsgTypeToString(nlMsgType));
Manojd9c93c22017-10-19 13:40:26 -0700276 LOG_IOV(*iovecs);
Nathan Harold1a371532017-01-30 12:30:48 -0800277
ludie51e3862017-08-15 19:28:12 -0700278 StatusOr<size_t> writeResult = getSyscallInstance().writev(mSock, *iovecs);
ludi4072ff22017-06-15 08:56:52 -0700279 if (!isOk(writeResult)) {
280 ALOGE("netlink socket writev failed (%s)", toString(writeResult).c_str());
ludi6e8eccd2017-08-14 14:40:37 -0700281 return writeResult;
Nathan Harold1a371532017-01-30 12:30:48 -0800282 }
283
ludi4072ff22017-06-15 08:56:52 -0700284 if (nlMsg.nlmsg_len != writeResult.value()) {
285 ALOGE("Invalid netlink message length sent %d", static_cast<int>(writeResult.value()));
ludi6e8eccd2017-08-14 14:40:37 -0700286 return netdutils::statusFromErrno(EBADMSG, "Invalid message length");
Nathan Harold1a371532017-01-30 12:30:48 -0800287 }
288
ludi4072ff22017-06-15 08:56:52 -0700289 NetlinkResponse response = {};
Nathan Harold1a371532017-01-30 12:30:48 -0800290
ludi4072ff22017-06-15 08:56:52 -0700291 StatusOr<Slice> readResult =
292 getSyscallInstance().read(Fd(mSock), netdutils::makeSlice(response));
293 if (!isOk(readResult)) {
294 ALOGE("netlink response error (%s)", toString(readResult).c_str());
ludi6e8eccd2017-08-14 14:40:37 -0700295 return readResult;
ludi4072ff22017-06-15 08:56:52 -0700296 }
297
298 LOG_HEX("netlink msg resp", reinterpret_cast<char*>(readResult.value().base()),
299 readResult.value().size());
300
ludi6e8eccd2017-08-14 14:40:37 -0700301 Status validateStatus = validateResponse(response, readResult.value().size());
302 if (!isOk(validateStatus)) {
303 ALOGE("netlink response contains error (%s)", toString(validateStatus).c_str());
304 }
305
306 return validateStatus;
Nathan Harold1a371532017-01-30 12:30:48 -0800307 }
308};
309
ludi6e8eccd2017-08-14 14:40:37 -0700310StatusOr<int> convertToXfrmAddr(const std::string& strAddr, xfrm_address_t* xfrmAddr) {
Nathan Harold1a371532017-01-30 12:30:48 -0800311 if (strAddr.length() == 0) {
312 memset(xfrmAddr, 0, sizeof(*xfrmAddr));
313 return AF_UNSPEC;
314 }
315
316 if (inet_pton(AF_INET6, strAddr.c_str(), reinterpret_cast<void*>(xfrmAddr))) {
317 return AF_INET6;
318 } else if (inet_pton(AF_INET, strAddr.c_str(), reinterpret_cast<void*>(xfrmAddr))) {
319 return AF_INET;
320 } else {
ludi6e8eccd2017-08-14 14:40:37 -0700321 return netdutils::statusFromErrno(EAFNOSUPPORT, "Invalid address family");
Nathan Harold1a371532017-01-30 12:30:48 -0800322 }
323}
324
325void fillXfrmNlaHdr(nlattr* hdr, uint16_t type, uint16_t len) {
326 hdr->nla_type = type;
327 hdr->nla_len = len;
328}
329
330void fillXfrmCurLifetimeDefaults(xfrm_lifetime_cur* cur) {
331 memset(reinterpret_cast<char*>(cur), 0, sizeof(*cur));
332}
333void fillXfrmLifetimeDefaults(xfrm_lifetime_cfg* cfg) {
334 cfg->soft_byte_limit = XFRM_INF;
335 cfg->hard_byte_limit = XFRM_INF;
336 cfg->soft_packet_limit = XFRM_INF;
337 cfg->hard_packet_limit = XFRM_INF;
338}
339
340/*
341 * Allocate SPIs within an (inclusive) range of min-max.
342 * returns 0 (INVALID_SPI) once the entire range has been parsed.
343 */
344class RandomSpi {
345public:
346 RandomSpi(int min, int max) : mMin(min) {
Nathan Harold1e284452017-10-10 13:31:19 -0700347 // Re-seeding should be safe because the seed itself is
348 // sufficiently random and we don't need secure random
349 std::mt19937 rnd = std::mt19937(std::random_device()());
350 mNext = std::uniform_int_distribution<>(1, INT_MAX)(rnd);
Nathan Harold1a371532017-01-30 12:30:48 -0800351 mSize = max - min + 1;
352 mCount = mSize;
353 }
354
355 uint32_t next() {
356 if (!mCount)
357 return 0;
358 mCount--;
359 return (mNext++ % mSize) + mMin;
360 }
361
362private:
363 uint32_t mNext;
364 uint32_t mSize;
365 uint32_t mMin;
366 uint32_t mCount;
367};
368
369} // namespace
370
371//
372// Begin XfrmController Impl
373//
374//
375XfrmController::XfrmController(void) {}
376
Nathan Harold21299f72018-03-16 20:13:03 -0700377netdutils::Status XfrmController::Init() {
378 RETURN_IF_NOT_OK(flushInterfaces());
379 XfrmSocketImpl sock;
380 RETURN_IF_NOT_OK(sock.open());
381 RETURN_IF_NOT_OK(flushSaDb(sock));
382 return flushPolicyDb(sock);
383}
384
385netdutils::Status XfrmController::flushInterfaces() {
386 const auto& ifaces = InterfaceController::getIfaceNames();
387 RETURN_IF_NOT_OK(ifaces);
Nathan Harold45c35662018-04-23 10:10:18 -0700388 const String8 ifPrefix8 = String8(INetd::IPSEC_INTERFACE_PREFIX().string());
Nathan Harold21299f72018-03-16 20:13:03 -0700389
390 for (const std::string& iface : ifaces.value()) {
391 int status = 0;
392 // Look for the reserved interface prefix, which must be in the name at position 0
Nathan Haroldb6bd53e2018-05-14 11:56:59 -0700393 if (android::base::StartsWith(iface.c_str(), ifPrefix8.c_str()) &&
Nathan Harold21299f72018-03-16 20:13:03 -0700394 (status = removeVirtualTunnelInterface(iface)) < 0) {
395 ALOGE("Failed to delete ipsec tunnel %s.", iface.c_str());
396 return netdutils::statusFromErrno(status, "Failed to remove ipsec tunnel.");
397 }
398 }
399 return netdutils::status::ok;
400}
401
402netdutils::Status XfrmController::flushSaDb(const XfrmSocket& s) {
403 struct xfrm_usersa_flush flushUserSa = {.proto = IPSEC_PROTO_ANY};
404
405 std::vector<iovec> iov = {{NULL, 0}, // reserved for the eventual addition of a NLMSG_HDR
406 {&flushUserSa, sizeof(flushUserSa)}, // xfrm_usersa_flush structure
407 {kPadBytes, NLMSG_ALIGN(sizeof(flushUserSa)) - sizeof(flushUserSa)}};
408
409 return s.sendMessage(XFRM_MSG_FLUSHSA, NETLINK_REQUEST_FLAGS, 0, &iov);
410}
411
412netdutils::Status XfrmController::flushPolicyDb(const XfrmSocket& s) {
413 std::vector<iovec> iov = {{NULL, 0}}; // reserved for the eventual addition of a NLMSG_HDR
414 return s.sendMessage(XFRM_MSG_FLUSHPOLICY, NETLINK_REQUEST_FLAGS, 0, &iov);
415}
416
Benedict Wongb2daefb2017-12-06 22:05:46 -0800417netdutils::Status XfrmController::ipSecSetEncapSocketOwner(const android::base::unique_fd& socket,
418 int newUid, uid_t callerUid) {
419 ALOGD("XfrmController:%s, line=%d", __FUNCTION__, __LINE__);
420
421 const int fd = socket.get();
422 struct stat info;
423 if (fstat(fd, &info)) {
424 return netdutils::statusFromErrno(errno, "Failed to stat socket file descriptor");
425 }
426 if (info.st_uid != callerUid) {
427 return netdutils::statusFromErrno(EPERM, "fchown disabled for non-owner calls");
428 }
Nathan Haroldda54f122018-01-09 16:42:57 -0800429 if (S_ISSOCK(info.st_mode) == 0) {
Benedict Wongb2daefb2017-12-06 22:05:46 -0800430 return netdutils::statusFromErrno(EINVAL, "File descriptor was not a socket");
431 }
432
433 int optval;
434 socklen_t optlen;
Nathan Haroldda54f122018-01-09 16:42:57 -0800435 netdutils::Status status =
436 getSyscallInstance().getsockopt(Fd(socket), IPPROTO_UDP, UDP_ENCAP, &optval, &optlen);
Benedict Wongb2daefb2017-12-06 22:05:46 -0800437 if (status != netdutils::status::ok) {
438 return status;
439 }
Nathan Haroldda54f122018-01-09 16:42:57 -0800440 if (optval != UDP_ENCAP_ESPINUDP && optval != UDP_ENCAP_ESPINUDP_NON_IKE) {
Benedict Wongb2daefb2017-12-06 22:05:46 -0800441 return netdutils::statusFromErrno(EINVAL, "Socket did not have UDP-encap sockopt set");
442 }
443 if (fchown(fd, newUid, -1)) {
444 return netdutils::statusFromErrno(errno, "Failed to fchown socket file descriptor");
445 }
446
447 return netdutils::status::ok;
448}
449
Nathan Haroldda54f122018-01-09 16:42:57 -0800450netdutils::Status XfrmController::ipSecAllocateSpi(int32_t transformId,
451 const std::string& sourceAddress,
452 const std::string& destinationAddress,
453 int32_t inSpi, int32_t* outSpi) {
Nathan Harold1a371532017-01-30 12:30:48 -0800454 ALOGD("XfrmController:%s, line=%d", __FUNCTION__, __LINE__);
455 ALOGD("transformId=%d", transformId);
Nathan Haroldda54f122018-01-09 16:42:57 -0800456 ALOGD("sourceAddress=%s", sourceAddress.c_str());
457 ALOGD("destinationAddress=%s", destinationAddress.c_str());
Nathan Harold1a371532017-01-30 12:30:48 -0800458 ALOGD("inSpi=%0.8x", inSpi);
459
460 XfrmSaInfo saInfo{};
ludi6e8eccd2017-08-14 14:40:37 -0700461 netdutils::Status ret =
Di Lu2ccb3e52018-01-03 16:19:20 -0800462 fillXfrmId(sourceAddress, destinationAddress, INVALID_SPI, 0, 0, transformId, &saInfo);
ludi6e8eccd2017-08-14 14:40:37 -0700463 if (!isOk(ret)) {
Nathan Harold1a371532017-01-30 12:30:48 -0800464 return ret;
465 }
466
467 XfrmSocketImpl sock;
ludi6e8eccd2017-08-14 14:40:37 -0700468 netdutils::Status socketStatus = sock.open();
469 if (!isOk(socketStatus)) {
Nathan Harold1a371532017-01-30 12:30:48 -0800470 ALOGD("Sock open failed for XFRM, line=%d", __LINE__);
ludi6e8eccd2017-08-14 14:40:37 -0700471 return socketStatus;
Nathan Harold1a371532017-01-30 12:30:48 -0800472 }
473
474 int minSpi = RAND_SPI_MIN, maxSpi = RAND_SPI_MAX;
475
476 if (inSpi)
477 minSpi = maxSpi = inSpi;
ludi6e8eccd2017-08-14 14:40:37 -0700478
Nathan Harold1a371532017-01-30 12:30:48 -0800479 ret = allocateSpi(saInfo, minSpi, maxSpi, reinterpret_cast<uint32_t*>(outSpi), sock);
ludi6e8eccd2017-08-14 14:40:37 -0700480 if (!isOk(ret)) {
481 // TODO: May want to return a new Status with a modified status string
Nathan Harold1a371532017-01-30 12:30:48 -0800482 ALOGD("Failed to Allocate an SPI, line=%d", __LINE__);
483 *outSpi = INVALID_SPI;
484 }
485
486 return ret;
487}
488
ludi6e8eccd2017-08-14 14:40:37 -0700489netdutils::Status XfrmController::ipSecAddSecurityAssociation(
Nathan Haroldda54f122018-01-09 16:42:57 -0800490 int32_t transformId, int32_t mode, const std::string& sourceAddress,
manojboopathi8707f232018-01-02 14:45:47 -0800491 const std::string& destinationAddress, int32_t underlyingNetId, int32_t spi, int32_t markValue,
492 int32_t markMask, const std::string& authAlgo, const std::vector<uint8_t>& authKey,
493 int32_t authTruncBits, const std::string& cryptAlgo, const std::vector<uint8_t>& cryptKey,
494 int32_t cryptTruncBits, const std::string& aeadAlgo, const std::vector<uint8_t>& aeadKey,
495 int32_t aeadIcvBits, int32_t encapType, int32_t encapLocalPort, int32_t encapRemotePort) {
Nathan Harold1a371532017-01-30 12:30:48 -0800496 ALOGD("XfrmController::%s, line=%d", __FUNCTION__, __LINE__);
497 ALOGD("transformId=%d", transformId);
498 ALOGD("mode=%d", mode);
Nathan Haroldda54f122018-01-09 16:42:57 -0800499 ALOGD("sourceAddress=%s", sourceAddress.c_str());
500 ALOGD("destinationAddress=%s", destinationAddress.c_str());
Benedict Wong96abf482018-01-22 13:56:41 -0800501 ALOGD("underlyingNetworkId=%d", underlyingNetId);
Nathan Harold1a371532017-01-30 12:30:48 -0800502 ALOGD("spi=%0.8x", spi);
Di Lu2ccb3e52018-01-03 16:19:20 -0800503 ALOGD("markValue=%x", markValue);
504 ALOGD("markMask=%x", markMask);
Nathan Harold1a371532017-01-30 12:30:48 -0800505 ALOGD("authAlgo=%s", authAlgo.c_str());
506 ALOGD("authTruncBits=%d", authTruncBits);
507 ALOGD("cryptAlgo=%s", cryptAlgo.c_str());
508 ALOGD("cryptTruncBits=%d,", cryptTruncBits);
Benedict Wongbe65b432017-08-22 21:43:14 -0700509 ALOGD("aeadAlgo=%s", aeadAlgo.c_str());
510 ALOGD("aeadIcvBits=%d,", aeadIcvBits);
Nathan Harold1a371532017-01-30 12:30:48 -0800511 ALOGD("encapType=%d", encapType);
512 ALOGD("encapLocalPort=%d", encapLocalPort);
513 ALOGD("encapRemotePort=%d", encapRemotePort);
514
515 XfrmSaInfo saInfo{};
Di Lu2ccb3e52018-01-03 16:19:20 -0800516 netdutils::Status ret = fillXfrmId(sourceAddress, destinationAddress, spi, markValue, markMask,
517 transformId, &saInfo);
ludi6e8eccd2017-08-14 14:40:37 -0700518 if (!isOk(ret)) {
Nathan Harold1a371532017-01-30 12:30:48 -0800519 return ret;
520 }
521
Nathan Harold1a371532017-01-30 12:30:48 -0800522 saInfo.auth = XfrmAlgo{
523 .name = authAlgo, .key = authKey, .truncLenBits = static_cast<uint16_t>(authTruncBits)};
524
525 saInfo.crypt = XfrmAlgo{
526 .name = cryptAlgo, .key = cryptKey, .truncLenBits = static_cast<uint16_t>(cryptTruncBits)};
527
Benedict Wongbe65b432017-08-22 21:43:14 -0700528 saInfo.aead = XfrmAlgo{
529 .name = aeadAlgo, .key = aeadKey, .truncLenBits = static_cast<uint16_t>(aeadIcvBits)};
530
Nathan Harold1a371532017-01-30 12:30:48 -0800531 switch (static_cast<XfrmMode>(mode)) {
532 case XfrmMode::TRANSPORT:
533 case XfrmMode::TUNNEL:
534 saInfo.mode = static_cast<XfrmMode>(mode);
535 break;
536 default:
ludi6e8eccd2017-08-14 14:40:37 -0700537 return netdutils::statusFromErrno(EINVAL, "Invalid xfrm mode");
Nathan Harold1a371532017-01-30 12:30:48 -0800538 }
539
540 XfrmSocketImpl sock;
ludi6e8eccd2017-08-14 14:40:37 -0700541 netdutils::Status socketStatus = sock.open();
542 if (!isOk(socketStatus)) {
Nathan Harold1a371532017-01-30 12:30:48 -0800543 ALOGD("Sock open failed for XFRM, line=%d", __LINE__);
ludi6e8eccd2017-08-14 14:40:37 -0700544 return socketStatus;
Nathan Harold1a371532017-01-30 12:30:48 -0800545 }
546
Nathan Harold420ceac2017-04-05 19:36:59 -0700547 switch (static_cast<XfrmEncapType>(encapType)) {
548 case XfrmEncapType::ESPINUDP:
549 case XfrmEncapType::ESPINUDP_NON_IKE:
550 if (saInfo.addrFamily != AF_INET) {
ludi6e8eccd2017-08-14 14:40:37 -0700551 return netdutils::statusFromErrno(EAFNOSUPPORT, "IPv6 encap not supported");
Nathan Harold420ceac2017-04-05 19:36:59 -0700552 }
Nathan Haroldda54f122018-01-09 16:42:57 -0800553 // The ports are not used on input SAs, so this is OK to be wrong when
554 // direction is ultimately input.
555 saInfo.encap.srcPort = encapLocalPort;
556 saInfo.encap.dstPort = encapRemotePort;
Nathan Harold420ceac2017-04-05 19:36:59 -0700557 // fall through
558 case XfrmEncapType::NONE:
559 saInfo.encap.type = static_cast<XfrmEncapType>(encapType);
560 break;
561 default:
ludi6e8eccd2017-08-14 14:40:37 -0700562 return netdutils::statusFromErrno(EINVAL, "Invalid encap type");
Nathan Harold420ceac2017-04-05 19:36:59 -0700563 }
564
Benedict Wong96abf482018-01-22 13:56:41 -0800565 saInfo.netId = underlyingNetId;
566
Di Lu0e16b5e2018-01-12 10:37:53 -0800567 ret = updateSecurityAssociation(saInfo, sock);
ludi6e8eccd2017-08-14 14:40:37 -0700568 if (!isOk(ret)) {
Di Lu0e16b5e2018-01-12 10:37:53 -0800569 ALOGD("Failed updating a Security Association, line=%d", __LINE__);
Nathan Harold1a371532017-01-30 12:30:48 -0800570 }
571
ludi6e8eccd2017-08-14 14:40:37 -0700572 return ret;
Nathan Harold1a371532017-01-30 12:30:48 -0800573}
574
Di Lu2ccb3e52018-01-03 16:19:20 -0800575netdutils::Status XfrmController::ipSecDeleteSecurityAssociation(
576 int32_t transformId, const std::string& sourceAddress, const std::string& destinationAddress,
577 int32_t spi, int32_t markValue, int32_t markMask) {
Nathan Harold1a371532017-01-30 12:30:48 -0800578 ALOGD("XfrmController:%s, line=%d", __FUNCTION__, __LINE__);
579 ALOGD("transformId=%d", transformId);
Nathan Haroldda54f122018-01-09 16:42:57 -0800580 ALOGD("sourceAddress=%s", sourceAddress.c_str());
581 ALOGD("destinationAddress=%s", destinationAddress.c_str());
Nathan Harold1a371532017-01-30 12:30:48 -0800582 ALOGD("spi=%0.8x", spi);
Di Lu2ccb3e52018-01-03 16:19:20 -0800583 ALOGD("markValue=%x", markValue);
584 ALOGD("markMask=%x", markMask);
Nathan Harold1a371532017-01-30 12:30:48 -0800585
Nathan Harold7441c692017-12-12 21:25:01 -0800586 XfrmId saId{};
Di Lu2ccb3e52018-01-03 16:19:20 -0800587 netdutils::Status ret =
588 fillXfrmId(sourceAddress, destinationAddress, spi, markValue, markMask, transformId, &saId);
ludi6e8eccd2017-08-14 14:40:37 -0700589 if (!isOk(ret)) {
Nathan Harold1a371532017-01-30 12:30:48 -0800590 return ret;
591 }
592
593 XfrmSocketImpl sock;
ludi6e8eccd2017-08-14 14:40:37 -0700594 netdutils::Status socketStatus = sock.open();
595 if (!isOk(socketStatus)) {
Nathan Harold1a371532017-01-30 12:30:48 -0800596 ALOGD("Sock open failed for XFRM, line=%d", __LINE__);
ludi6e8eccd2017-08-14 14:40:37 -0700597 return socketStatus;
Nathan Harold1a371532017-01-30 12:30:48 -0800598 }
599
600 ret = deleteSecurityAssociation(saId, sock);
ludi6e8eccd2017-08-14 14:40:37 -0700601 if (!isOk(ret)) {
Nathan Harold1a371532017-01-30 12:30:48 -0800602 ALOGD("Failed to delete Security Association, line=%d", __LINE__);
Nathan Harold1a371532017-01-30 12:30:48 -0800603 }
604
605 return ret;
606}
607
Nathan Haroldda54f122018-01-09 16:42:57 -0800608netdutils::Status XfrmController::fillXfrmId(const std::string& sourceAddress,
609 const std::string& destinationAddress, int32_t spi,
Di Lu2ccb3e52018-01-03 16:19:20 -0800610 int32_t markValue, int32_t markMask,
Nathan Harold7441c692017-12-12 21:25:01 -0800611 int32_t transformId, XfrmId* xfrmId) {
612 // Fill the straightforward fields first
613 xfrmId->transformId = transformId;
Nathan Harold7441c692017-12-12 21:25:01 -0800614 xfrmId->spi = htonl(spi);
Di Lu2ccb3e52018-01-03 16:19:20 -0800615 xfrmId->mark.v = markValue;
616 xfrmId->mark.m = markMask;
Nathan Harold1a371532017-01-30 12:30:48 -0800617
Nathan Harold7441c692017-12-12 21:25:01 -0800618 // Use the addresses to determine the address family and do validation
Nathan Haroldda54f122018-01-09 16:42:57 -0800619 xfrm_address_t sourceXfrmAddr{}, destXfrmAddr{};
620 StatusOr<int> sourceFamily, destFamily;
621 sourceFamily = convertToXfrmAddr(sourceAddress, &sourceXfrmAddr);
622 destFamily = convertToXfrmAddr(destinationAddress, &destXfrmAddr);
623 if (!isOk(sourceFamily) || !isOk(destFamily)) {
624 return netdutils::statusFromErrno(EINVAL, "Invalid address " + sourceAddress + "/" +
625 destinationAddress);
Nathan Harold1a371532017-01-30 12:30:48 -0800626 }
627
Nathan Haroldda54f122018-01-09 16:42:57 -0800628 if (destFamily.value() == AF_UNSPEC ||
629 (sourceFamily.value() != AF_UNSPEC && sourceFamily.value() != destFamily.value())) {
630 ALOGD("Invalid or Mismatched Address Families, %d != %d, line=%d", sourceFamily.value(),
631 destFamily.value(), __LINE__);
ludi6e8eccd2017-08-14 14:40:37 -0700632 return netdutils::statusFromErrno(EINVAL, "Invalid or mismatched address families");
Nathan Harold1a371532017-01-30 12:30:48 -0800633 }
634
Nathan Haroldda54f122018-01-09 16:42:57 -0800635 xfrmId->addrFamily = destFamily.value();
Nathan Harold1a371532017-01-30 12:30:48 -0800636
Nathan Haroldda54f122018-01-09 16:42:57 -0800637 xfrmId->dstAddr = destXfrmAddr;
638 xfrmId->srcAddr = sourceXfrmAddr;
ludi6e8eccd2017-08-14 14:40:37 -0700639 return netdutils::status::ok;
Nathan Harold1a371532017-01-30 12:30:48 -0800640}
641
ludi6e8eccd2017-08-14 14:40:37 -0700642netdutils::Status XfrmController::ipSecApplyTransportModeTransform(
643 const android::base::unique_fd& socket, int32_t transformId, int32_t direction,
Nathan Haroldda54f122018-01-09 16:42:57 -0800644 const std::string& sourceAddress, const std::string& destinationAddress, int32_t spi) {
Nathan Harold1a371532017-01-30 12:30:48 -0800645 ALOGD("XfrmController::%s, line=%d", __FUNCTION__, __LINE__);
646 ALOGD("transformId=%d", transformId);
647 ALOGD("direction=%d", direction);
Nathan Haroldda54f122018-01-09 16:42:57 -0800648 ALOGD("sourceAddress=%s", sourceAddress.c_str());
649 ALOGD("destinationAddress=%s", destinationAddress.c_str());
Nathan Harold1a371532017-01-30 12:30:48 -0800650 ALOGD("spi=%0.8x", spi);
651
ludi4072ff22017-06-15 08:56:52 -0700652 StatusOr<sockaddr_storage> ret = getSyscallInstance().getsockname<sockaddr_storage>(Fd(socket));
653 if (!isOk(ret)) {
Nathan Harold1a371532017-01-30 12:30:48 -0800654 ALOGE("Failed to get socket info in %s", __FUNCTION__);
ludi6e8eccd2017-08-14 14:40:37 -0700655 return ret;
Nathan Harold1a371532017-01-30 12:30:48 -0800656 }
Nathan Harold7441c692017-12-12 21:25:01 -0800657 struct sockaddr_storage saddr = ret.value();
ludi4072ff22017-06-15 08:56:52 -0700658
Nathan Harold1a371532017-01-30 12:30:48 -0800659 XfrmSaInfo saInfo{};
Nathan Harold7441c692017-12-12 21:25:01 -0800660 netdutils::Status status =
Di Lu2ccb3e52018-01-03 16:19:20 -0800661 fillXfrmId(sourceAddress, destinationAddress, spi, 0, 0, transformId, &saInfo);
ludi6e8eccd2017-08-14 14:40:37 -0700662 if (!isOk(status)) {
Nathan Harold1a371532017-01-30 12:30:48 -0800663 ALOGE("Couldn't build SA ID %s", __FUNCTION__);
ludi6e8eccd2017-08-14 14:40:37 -0700664 return status;
Nathan Harold1a371532017-01-30 12:30:48 -0800665 }
666
manojboopathi26f42922017-12-14 10:51:57 -0800667 if (saddr.ss_family == AF_INET && saInfo.addrFamily != AF_INET) {
668 ALOGE("IPV4 socket address family(%d) should match IPV4 Transform "
669 "address family(%d)!",
670 saddr.ss_family, saInfo.addrFamily);
ludi6e8eccd2017-08-14 14:40:37 -0700671 return netdutils::statusFromErrno(EINVAL, "Mismatched address family");
Nathan Harold1a371532017-01-30 12:30:48 -0800672 }
673
674 struct {
675 xfrm_userpolicy_info info;
676 xfrm_user_tmpl tmpl;
677 } policy{};
678
Nathan Haroldda54f122018-01-09 16:42:57 -0800679 fillTransportModeUserSpInfo(saInfo, static_cast<XfrmDirection>(direction), &policy.info);
Nathan Harold1a371532017-01-30 12:30:48 -0800680 fillUserTemplate(saInfo, &policy.tmpl);
681
682 LOG_HEX("XfrmUserPolicy", reinterpret_cast<char*>(&policy), sizeof(policy));
683
684 int sockOpt, sockLayer;
manojboopathi26f42922017-12-14 10:51:57 -0800685 switch (saddr.ss_family) {
Nathan Harold1a371532017-01-30 12:30:48 -0800686 case AF_INET:
687 sockOpt = IP_XFRM_POLICY;
688 sockLayer = SOL_IP;
689 break;
690 case AF_INET6:
691 sockOpt = IPV6_XFRM_POLICY;
692 sockLayer = SOL_IPV6;
693 break;
694 default:
ludi6e8eccd2017-08-14 14:40:37 -0700695 return netdutils::statusFromErrno(EAFNOSUPPORT, "Invalid address family");
Nathan Harold1a371532017-01-30 12:30:48 -0800696 }
697
ludi6e8eccd2017-08-14 14:40:37 -0700698 status = getSyscallInstance().setsockopt(Fd(socket), sockLayer, sockOpt, policy);
ludi4072ff22017-06-15 08:56:52 -0700699 if (!isOk(status)) {
700 ALOGE("Error setting socket option for XFRM! (%s)", toString(status).c_str());
Nathan Harold1a371532017-01-30 12:30:48 -0800701 }
ludi6e8eccd2017-08-14 14:40:37 -0700702
703 return status;
Nathan Harold1a371532017-01-30 12:30:48 -0800704}
705
ludi6e8eccd2017-08-14 14:40:37 -0700706netdutils::Status
707XfrmController::ipSecRemoveTransportModeTransform(const android::base::unique_fd& socket) {
ludi87991632017-10-30 15:28:11 -0700708 ALOGD("XfrmController::%s, line=%d", __FUNCTION__, __LINE__);
709
710 StatusOr<sockaddr_storage> ret = getSyscallInstance().getsockname<sockaddr_storage>(Fd(socket));
711 if (!isOk(ret)) {
712 ALOGE("Failed to get socket info in %s! (%s)", __FUNCTION__, toString(ret).c_str());
713 return ret;
714 }
715
716 int sockOpt, sockLayer;
717 switch (ret.value().ss_family) {
718 case AF_INET:
719 sockOpt = IP_XFRM_POLICY;
720 sockLayer = SOL_IP;
721 break;
722 case AF_INET6:
723 sockOpt = IPV6_XFRM_POLICY;
724 sockLayer = SOL_IPV6;
725 break;
726 default:
727 return netdutils::statusFromErrno(EAFNOSUPPORT, "Invalid address family");
728 }
729
730 // Kernel will delete the security policy on this socket for both direction
731 // if optval is set to NULL and optlen is set to 0.
732 netdutils::Status status =
733 getSyscallInstance().setsockopt(Fd(socket), sockLayer, sockOpt, NULL, 0);
734 if (!isOk(status)) {
735 ALOGE("Error removing socket option for XFRM! (%s)", toString(status).c_str());
736 }
737
738 return status;
Nathan Harold1a371532017-01-30 12:30:48 -0800739}
740
ludi771b8002017-11-20 15:09:05 -0800741netdutils::Status XfrmController::ipSecAddSecurityPolicy(int32_t transformId, int32_t direction,
742 const std::string& localAddress,
743 const std::string& remoteAddress,
Di Lu2ccb3e52018-01-03 16:19:20 -0800744 int32_t spi, int32_t markValue,
745 int32_t markMask) {
ludi771b8002017-11-20 15:09:05 -0800746 return processSecurityPolicy(transformId, direction, localAddress, remoteAddress, spi,
Di Lu2ccb3e52018-01-03 16:19:20 -0800747 markValue, markMask, XFRM_MSG_NEWPOLICY);
ludi771b8002017-11-20 15:09:05 -0800748}
749
750netdutils::Status XfrmController::ipSecUpdateSecurityPolicy(int32_t transformId, int32_t direction,
751 const std::string& localAddress,
752 const std::string& remoteAddress,
Di Lu2ccb3e52018-01-03 16:19:20 -0800753 int32_t spi, int32_t markValue,
754 int32_t markMask) {
ludi771b8002017-11-20 15:09:05 -0800755 return processSecurityPolicy(transformId, direction, localAddress, remoteAddress, spi,
Di Lu2ccb3e52018-01-03 16:19:20 -0800756 markValue, markMask, XFRM_MSG_UPDPOLICY);
ludi771b8002017-11-20 15:09:05 -0800757}
758
759netdutils::Status XfrmController::ipSecDeleteSecurityPolicy(int32_t transformId, int32_t direction,
760 const std::string& localAddress,
Di Lu2ccb3e52018-01-03 16:19:20 -0800761 const std::string& remoteAddress,
762 int32_t markValue, int32_t markMask) {
manojboopathi8707f232018-01-02 14:45:47 -0800763 return processSecurityPolicy(transformId, direction, localAddress, remoteAddress, 0, markValue,
764 markMask, XFRM_MSG_DELPOLICY);
ludi771b8002017-11-20 15:09:05 -0800765}
766
767netdutils::Status XfrmController::processSecurityPolicy(int32_t transformId, int32_t direction,
768 const std::string& localAddress,
769 const std::string& remoteAddress,
Di Lu2ccb3e52018-01-03 16:19:20 -0800770 int32_t spi, int32_t markValue,
771 int32_t markMask, int32_t msgType) {
ludi771b8002017-11-20 15:09:05 -0800772 ALOGD("XfrmController::%s, line=%d", __FUNCTION__, __LINE__);
773 ALOGD("transformId=%d", transformId);
774 ALOGD("direction=%d", direction);
775 ALOGD("localAddress=%s", localAddress.c_str());
776 ALOGD("remoteAddress=%s", remoteAddress.c_str());
777 ALOGD("spi=%0.8x", spi);
Di Lu2ccb3e52018-01-03 16:19:20 -0800778 ALOGD("markValue=%d", markValue);
779 ALOGD("markMask=%d", markMask);
ludi771b8002017-11-20 15:09:05 -0800780 ALOGD("msgType=%d", msgType);
781
782 XfrmSaInfo saInfo{};
783 saInfo.mode = XfrmMode::TUNNEL;
784
785 XfrmSocketImpl sock;
786 RETURN_IF_NOT_OK(sock.open());
787
Di Lu2ccb3e52018-01-03 16:19:20 -0800788 RETURN_IF_NOT_OK(
789 fillXfrmId(localAddress, remoteAddress, spi, markValue, markMask, transformId, &saInfo));
ludi771b8002017-11-20 15:09:05 -0800790
791 if (msgType == XFRM_MSG_DELPOLICY) {
792 return deleteTunnelModeSecurityPolicy(saInfo, sock, static_cast<XfrmDirection>(direction));
793 } else {
794 return updateTunnelModeSecurityPolicy(saInfo, sock, static_cast<XfrmDirection>(direction),
795 msgType);
796 }
797}
798
799void XfrmController::fillXfrmSelector(const XfrmSaInfo& record, xfrm_selector* selector) {
Nathan Harold1a371532017-01-30 12:30:48 -0800800 selector->family = record.addrFamily;
manojboopathi8707f232018-01-02 14:45:47 -0800801 selector->proto = AF_UNSPEC; // TODO: do we need to match the protocol? it's
802 // possible via the socket
Nathan Harold1a371532017-01-30 12:30:48 -0800803}
804
Di Lu0e16b5e2018-01-12 10:37:53 -0800805netdutils::Status XfrmController::updateSecurityAssociation(const XfrmSaInfo& record,
manojboopathi4d2d6f12017-12-06 11:11:31 -0800806 const XfrmSocket& sock) {
Nathan Harold1a371532017-01-30 12:30:48 -0800807 xfrm_usersa_info usersa{};
808 nlattr_algo_crypt crypt{};
809 nlattr_algo_auth auth{};
Benedict Wongbe65b432017-08-22 21:43:14 -0700810 nlattr_algo_aead aead{};
Di Lu2ccb3e52018-01-03 16:19:20 -0800811 nlattr_xfrm_mark xfrmmark{};
Benedict Wong96abf482018-01-22 13:56:41 -0800812 nlattr_xfrm_output_mark xfrmoutputmark{};
Nathan Harold420ceac2017-04-05 19:36:59 -0700813 nlattr_encap_tmpl encap{};
Nathan Harold1a371532017-01-30 12:30:48 -0800814
Benedict Wongbe65b432017-08-22 21:43:14 -0700815 enum {
816 NLMSG_HDR,
817 USERSA,
818 USERSA_PAD,
819 CRYPT,
820 CRYPT_PAD,
821 AUTH,
822 AUTH_PAD,
823 AEAD,
824 AEAD_PAD,
Di Lu2ccb3e52018-01-03 16:19:20 -0800825 MARK,
826 MARK_PAD,
Benedict Wong96abf482018-01-22 13:56:41 -0800827 OUTPUT_MARK,
828 OUTPUT_MARK_PAD,
Benedict Wongbe65b432017-08-22 21:43:14 -0700829 ENCAP,
Di Lu2ccb3e52018-01-03 16:19:20 -0800830 ENCAP_PAD,
Benedict Wongbe65b432017-08-22 21:43:14 -0700831 };
Nathan Harold1a371532017-01-30 12:30:48 -0800832
ludie51e3862017-08-15 19:28:12 -0700833 std::vector<iovec> iov = {
Benedict Wong96abf482018-01-22 13:56:41 -0800834 {NULL, 0}, // reserved for the eventual addition of a NLMSG_HDR
835 {&usersa, 0}, // main usersa_info struct
836 {kPadBytes, 0}, // up to NLMSG_ALIGNTO pad bytes of padding
837 {&crypt, 0}, // adjust size if crypt algo is present
838 {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
839 {&auth, 0}, // adjust size if auth algo is present
840 {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
841 {&aead, 0}, // adjust size if aead algo is present
842 {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
843 {&xfrmmark, 0}, // adjust size if xfrm mark is present
844 {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
845 {&xfrmoutputmark, 0}, // adjust size if xfrm output mark is present
846 {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
847 {&encap, 0}, // adjust size if encapsulating
848 {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
Nathan Harold1a371532017-01-30 12:30:48 -0800849 };
850
Benedict Wongbe65b432017-08-22 21:43:14 -0700851 if (!record.aead.name.empty() && (!record.auth.name.empty() || !record.crypt.name.empty())) {
852 return netdutils::statusFromErrno(EINVAL, "Invalid xfrm algo selection; AEAD is mutually "
853 "exclusive with both Authentication and "
854 "Encryption");
855 }
856
Benedict Wong4f60ee12017-10-10 12:27:25 -0700857 if (record.aead.key.size() > MAX_KEY_LENGTH || record.auth.key.size() > MAX_KEY_LENGTH ||
858 record.crypt.key.size() > MAX_KEY_LENGTH) {
859 return netdutils::statusFromErrno(EINVAL, "Key length invalid; exceeds MAX_KEY_LENGTH");
Benedict Wongbe65b432017-08-22 21:43:14 -0700860 }
861
Nathan Harold1a371532017-01-30 12:30:48 -0800862 int len;
863 len = iov[USERSA].iov_len = fillUserSaInfo(record, &usersa);
864 iov[USERSA_PAD].iov_len = NLMSG_ALIGN(len) - len;
865
866 len = iov[CRYPT].iov_len = fillNlAttrXfrmAlgoEnc(record.crypt, &crypt);
867 iov[CRYPT_PAD].iov_len = NLA_ALIGN(len) - len;
868
869 len = iov[AUTH].iov_len = fillNlAttrXfrmAlgoAuth(record.auth, &auth);
870 iov[AUTH_PAD].iov_len = NLA_ALIGN(len) - len;
871
Benedict Wongbe65b432017-08-22 21:43:14 -0700872 len = iov[AEAD].iov_len = fillNlAttrXfrmAlgoAead(record.aead, &aead);
873 iov[AEAD_PAD].iov_len = NLA_ALIGN(len) - len;
874
Di Lu2ccb3e52018-01-03 16:19:20 -0800875 len = iov[MARK].iov_len = fillNlAttrXfrmMark(record, &xfrmmark);
876 iov[MARK_PAD].iov_len = NLA_ALIGN(len) - len;
877
Benedict Wong96abf482018-01-22 13:56:41 -0800878 len = iov[OUTPUT_MARK].iov_len = fillNlAttrXfrmOutputMark(record.netId, &xfrmoutputmark);
879 iov[OUTPUT_MARK_PAD].iov_len = NLA_ALIGN(len) - len;
880
Nathan Harold420ceac2017-04-05 19:36:59 -0700881 len = iov[ENCAP].iov_len = fillNlAttrXfrmEncapTmpl(record, &encap);
882 iov[ENCAP_PAD].iov_len = NLA_ALIGN(len) - len;
Di Lu2ccb3e52018-01-03 16:19:20 -0800883
ludie51e3862017-08-15 19:28:12 -0700884 return sock.sendMessage(XFRM_MSG_UPDSA, NETLINK_REQUEST_FLAGS, 0, &iov);
Nathan Harold1a371532017-01-30 12:30:48 -0800885}
886
887int XfrmController::fillNlAttrXfrmAlgoEnc(const XfrmAlgo& inAlgo, nlattr_algo_crypt* algo) {
Benedict Wongbe65b432017-08-22 21:43:14 -0700888 if (inAlgo.name.empty()) { // Do not fill anything if algorithm not provided
889 return 0;
890 }
891
Nathan Harold1a371532017-01-30 12:30:48 -0800892 int len = NLA_HDRLEN + sizeof(xfrm_algo);
Benedict Wongbe65b432017-08-22 21:43:14 -0700893 // Kernel always changes last char to null terminator; no safety checks needed.
Nathan Harold1a371532017-01-30 12:30:48 -0800894 strncpy(algo->crypt.alg_name, inAlgo.name.c_str(), sizeof(algo->crypt.alg_name));
Nathan Harold7441c692017-12-12 21:25:01 -0800895 algo->crypt.alg_key_len = inAlgo.key.size() * 8; // bits
Benedict Wongbe65b432017-08-22 21:43:14 -0700896 memcpy(algo->key, &inAlgo.key[0], inAlgo.key.size());
Nathan Harold1a371532017-01-30 12:30:48 -0800897 len += inAlgo.key.size();
898 fillXfrmNlaHdr(&algo->hdr, XFRMA_ALG_CRYPT, len);
899 return len;
900}
901
902int XfrmController::fillNlAttrXfrmAlgoAuth(const XfrmAlgo& inAlgo, nlattr_algo_auth* algo) {
Benedict Wongbe65b432017-08-22 21:43:14 -0700903 if (inAlgo.name.empty()) { // Do not fill anything if algorithm not provided
904 return 0;
905 }
906
Nathan Harold1a371532017-01-30 12:30:48 -0800907 int len = NLA_HDRLEN + sizeof(xfrm_algo_auth);
Benedict Wongbe65b432017-08-22 21:43:14 -0700908 // Kernel always changes last char to null terminator; no safety checks needed.
Nathan Harold1a371532017-01-30 12:30:48 -0800909 strncpy(algo->auth.alg_name, inAlgo.name.c_str(), sizeof(algo->auth.alg_name));
910 algo->auth.alg_key_len = inAlgo.key.size() * 8; // bits
911
912 // This is the extra field for ALG_AUTH_TRUNC
913 algo->auth.alg_trunc_len = inAlgo.truncLenBits;
914
Benedict Wongbe65b432017-08-22 21:43:14 -0700915 memcpy(algo->key, &inAlgo.key[0], inAlgo.key.size());
Nathan Harold1a371532017-01-30 12:30:48 -0800916 len += inAlgo.key.size();
917
918 fillXfrmNlaHdr(&algo->hdr, XFRMA_ALG_AUTH_TRUNC, len);
919 return len;
920}
921
Benedict Wongbe65b432017-08-22 21:43:14 -0700922int XfrmController::fillNlAttrXfrmAlgoAead(const XfrmAlgo& inAlgo, nlattr_algo_aead* algo) {
923 if (inAlgo.name.empty()) { // Do not fill anything if algorithm not provided
924 return 0;
925 }
926
927 int len = NLA_HDRLEN + sizeof(xfrm_algo_aead);
928 // Kernel always changes last char to null terminator; no safety checks needed.
929 strncpy(algo->aead.alg_name, inAlgo.name.c_str(), sizeof(algo->aead.alg_name));
930 algo->aead.alg_key_len = inAlgo.key.size() * 8; // bits
931
932 // This is the extra field for ALG_AEAD. ICV length is the same as truncation length
933 // for any AEAD algorithm.
934 algo->aead.alg_icv_len = inAlgo.truncLenBits;
935
936 memcpy(algo->key, &inAlgo.key[0], inAlgo.key.size());
937 len += inAlgo.key.size();
938
939 fillXfrmNlaHdr(&algo->hdr, XFRMA_ALG_AEAD, len);
940 return len;
941}
942
Nathan Harold420ceac2017-04-05 19:36:59 -0700943int XfrmController::fillNlAttrXfrmEncapTmpl(const XfrmSaInfo& record, nlattr_encap_tmpl* tmpl) {
944 if (record.encap.type == XfrmEncapType::NONE) {
945 return 0;
946 }
947
948 int len = NLA_HDRLEN + sizeof(xfrm_encap_tmpl);
949 tmpl->tmpl.encap_type = static_cast<uint16_t>(record.encap.type);
950 tmpl->tmpl.encap_sport = htons(record.encap.srcPort);
951 tmpl->tmpl.encap_dport = htons(record.encap.dstPort);
952 fillXfrmNlaHdr(&tmpl->hdr, XFRMA_ENCAP, len);
953 return len;
954}
955
Nathan Harold1a371532017-01-30 12:30:48 -0800956int XfrmController::fillUserSaInfo(const XfrmSaInfo& record, xfrm_usersa_info* usersa) {
ludi771b8002017-11-20 15:09:05 -0800957 fillXfrmSelector(record, &usersa->sel);
Nathan Harold1a371532017-01-30 12:30:48 -0800958
959 usersa->id.proto = IPPROTO_ESP;
960 usersa->id.spi = record.spi;
961 usersa->id.daddr = record.dstAddr;
962
963 usersa->saddr = record.srcAddr;
964
965 fillXfrmLifetimeDefaults(&usersa->lft);
966 fillXfrmCurLifetimeDefaults(&usersa->curlft);
967 memset(&usersa->stats, 0, sizeof(usersa->stats)); // leave stats zeroed out
968 usersa->reqid = record.transformId;
969 usersa->family = record.addrFamily;
970 usersa->mode = static_cast<uint8_t>(record.mode);
971 usersa->replay_window = REPLAY_WINDOW_SIZE;
manojboopathi4d2d6f12017-12-06 11:11:31 -0800972
973 if (record.mode == XfrmMode::TRANSPORT) {
974 usersa->flags = 0; // TODO: should we actually set flags, XFRM_SA_XFLAG_DONT_ENCAP_DSCP?
975 } else {
976 usersa->flags = XFRM_STATE_AF_UNSPEC;
977 }
978
Nathan Harold1a371532017-01-30 12:30:48 -0800979 return sizeof(*usersa);
980}
981
Nathan Harold7441c692017-12-12 21:25:01 -0800982int XfrmController::fillUserSaId(const XfrmId& record, xfrm_usersa_id* said) {
Nathan Harold1a371532017-01-30 12:30:48 -0800983 said->daddr = record.dstAddr;
984 said->spi = record.spi;
985 said->family = record.addrFamily;
986 said->proto = IPPROTO_ESP;
987
988 return sizeof(*said);
989}
990
Nathan Harold7441c692017-12-12 21:25:01 -0800991netdutils::Status XfrmController::deleteSecurityAssociation(const XfrmId& record,
ludi6e8eccd2017-08-14 14:40:37 -0700992 const XfrmSocket& sock) {
Nathan Harold1a371532017-01-30 12:30:48 -0800993 xfrm_usersa_id said{};
Di Lu2ccb3e52018-01-03 16:19:20 -0800994 nlattr_xfrm_mark xfrmmark{};
Nathan Harold1a371532017-01-30 12:30:48 -0800995
Di Lu2ccb3e52018-01-03 16:19:20 -0800996 enum { NLMSG_HDR, USERSAID, USERSAID_PAD, MARK, MARK_PAD };
Nathan Harold1a371532017-01-30 12:30:48 -0800997
ludie51e3862017-08-15 19:28:12 -0700998 std::vector<iovec> iov = {
Nathan Harold1a371532017-01-30 12:30:48 -0800999 {NULL, 0}, // reserved for the eventual addition of a NLMSG_HDR
1000 {&said, 0}, // main usersa_info struct
1001 {kPadBytes, 0}, // up to NLMSG_ALIGNTO pad bytes of padding
manojboopathi8707f232018-01-02 14:45:47 -08001002 {&xfrmmark, 0}, // adjust size if xfrm mark is present
1003 {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
Nathan Harold1a371532017-01-30 12:30:48 -08001004 };
1005
1006 int len;
1007 len = iov[USERSAID].iov_len = fillUserSaId(record, &said);
1008 iov[USERSAID_PAD].iov_len = NLMSG_ALIGN(len) - len;
1009
Di Lu2ccb3e52018-01-03 16:19:20 -08001010 len = iov[MARK].iov_len = fillNlAttrXfrmMark(record, &xfrmmark);
1011 iov[MARK_PAD].iov_len = NLA_ALIGN(len) - len;
1012
ludie51e3862017-08-15 19:28:12 -07001013 return sock.sendMessage(XFRM_MSG_DELSA, NETLINK_REQUEST_FLAGS, 0, &iov);
Nathan Harold1a371532017-01-30 12:30:48 -08001014}
1015
ludi6e8eccd2017-08-14 14:40:37 -07001016netdutils::Status XfrmController::allocateSpi(const XfrmSaInfo& record, uint32_t minSpi,
1017 uint32_t maxSpi, uint32_t* outSpi,
1018 const XfrmSocket& sock) {
Nathan Harold1a371532017-01-30 12:30:48 -08001019 xfrm_userspi_info spiInfo{};
1020
ludie51e3862017-08-15 19:28:12 -07001021 enum { NLMSG_HDR, USERSAID, USERSAID_PAD };
Nathan Harold1a371532017-01-30 12:30:48 -08001022
ludie51e3862017-08-15 19:28:12 -07001023 std::vector<iovec> iov = {
Nathan Harold1a371532017-01-30 12:30:48 -08001024 {NULL, 0}, // reserved for the eventual addition of a NLMSG_HDR
1025 {&spiInfo, 0}, // main userspi_info struct
1026 {kPadBytes, 0}, // up to NLMSG_ALIGNTO pad bytes of padding
1027 };
1028
1029 int len;
1030 if (fillUserSaInfo(record, &spiInfo.info) == 0) {
1031 ALOGE("Failed to fill transport SA Info");
1032 }
1033
1034 len = iov[USERSAID].iov_len = sizeof(spiInfo);
1035 iov[USERSAID_PAD].iov_len = NLMSG_ALIGN(len) - len;
1036
1037 RandomSpi spiGen = RandomSpi(minSpi, maxSpi);
ludi6e8eccd2017-08-14 14:40:37 -07001038 int spi;
1039 netdutils::Status ret;
Nathan Harold1a371532017-01-30 12:30:48 -08001040 while ((spi = spiGen.next()) != INVALID_SPI) {
1041 spiInfo.min = spi;
1042 spiInfo.max = spi;
ludie51e3862017-08-15 19:28:12 -07001043 ret = sock.sendMessage(XFRM_MSG_ALLOCSPI, NETLINK_REQUEST_FLAGS, 0, &iov);
Nathan Harold1a371532017-01-30 12:30:48 -08001044
1045 /* If the SPI is in use, we'll get ENOENT */
ludi6e8eccd2017-08-14 14:40:37 -07001046 if (netdutils::equalToErrno(ret, ENOENT))
Nathan Harold1a371532017-01-30 12:30:48 -08001047 continue;
1048
ludi6e8eccd2017-08-14 14:40:37 -07001049 if (isOk(ret)) {
Nathan Harold1a371532017-01-30 12:30:48 -08001050 *outSpi = spi;
Nathan Harold420ceac2017-04-05 19:36:59 -07001051 ALOGD("Allocated an SPI: %x", *outSpi);
Nathan Harold1a371532017-01-30 12:30:48 -08001052 } else {
1053 *outSpi = INVALID_SPI;
ludi6e8eccd2017-08-14 14:40:37 -07001054 ALOGE("SPI Allocation Failed with error %d", ret.code());
Nathan Harold1a371532017-01-30 12:30:48 -08001055 }
1056
1057 return ret;
1058 }
1059
1060 // Should always be -ENOENT if we get here
1061 return ret;
1062}
1063
ludi771b8002017-11-20 15:09:05 -08001064netdutils::Status XfrmController::updateTunnelModeSecurityPolicy(const XfrmSaInfo& record,
1065 const XfrmSocket& sock,
1066 XfrmDirection direction,
1067 uint16_t msgType) {
1068 xfrm_userpolicy_info userpolicy{};
1069 nlattr_user_tmpl usertmpl{};
Di Lu2ccb3e52018-01-03 16:19:20 -08001070 nlattr_xfrm_mark xfrmmark{};
ludi771b8002017-11-20 15:09:05 -08001071
1072 enum {
1073 NLMSG_HDR,
1074 USERPOLICY,
1075 USERPOLICY_PAD,
1076 USERTMPL,
1077 USERTMPL_PAD,
Di Lu2ccb3e52018-01-03 16:19:20 -08001078 MARK,
1079 MARK_PAD,
ludi771b8002017-11-20 15:09:05 -08001080 };
1081
1082 std::vector<iovec> iov = {
1083 {NULL, 0}, // reserved for the eventual addition of a NLMSG_HDR
1084 {&userpolicy, 0}, // main xfrm_userpolicy_info struct
1085 {kPadBytes, 0}, // up to NLMSG_ALIGNTO pad bytes of padding
1086 {&usertmpl, 0}, // adjust size if xfrm_user_tmpl struct is present
1087 {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
Di Lu2ccb3e52018-01-03 16:19:20 -08001088 {&xfrmmark, 0}, // adjust size if xfrm mark is present
1089 {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
ludi771b8002017-11-20 15:09:05 -08001090 };
1091
1092 int len;
1093 len = iov[USERPOLICY].iov_len = fillTransportModeUserSpInfo(record, direction, &userpolicy);
1094 iov[USERPOLICY_PAD].iov_len = NLMSG_ALIGN(len) - len;
1095
1096 len = iov[USERTMPL].iov_len = fillNlAttrUserTemplate(record, &usertmpl);
1097 iov[USERTMPL_PAD].iov_len = NLA_ALIGN(len) - len;
1098
Di Lu2ccb3e52018-01-03 16:19:20 -08001099 len = iov[MARK].iov_len = fillNlAttrXfrmMark(record, &xfrmmark);
1100 iov[MARK_PAD].iov_len = NLA_ALIGN(len) - len;
1101
ludi771b8002017-11-20 15:09:05 -08001102 return sock.sendMessage(msgType, NETLINK_REQUEST_FLAGS, 0, &iov);
1103}
1104
1105netdutils::Status XfrmController::deleteTunnelModeSecurityPolicy(const XfrmSaInfo& record,
1106 const XfrmSocket& sock,
1107 XfrmDirection direction) {
1108 xfrm_userpolicy_id policyid{};
Di Lu2ccb3e52018-01-03 16:19:20 -08001109 nlattr_xfrm_mark xfrmmark{};
ludi771b8002017-11-20 15:09:05 -08001110
1111 enum {
1112 NLMSG_HDR,
1113 USERPOLICYID,
1114 USERPOLICYID_PAD,
Di Lu2ccb3e52018-01-03 16:19:20 -08001115 MARK,
1116 MARK_PAD,
ludi771b8002017-11-20 15:09:05 -08001117 };
1118
1119 std::vector<iovec> iov = {
1120 {NULL, 0}, // reserved for the eventual addition of a NLMSG_HDR
1121 {&policyid, 0}, // main xfrm_userpolicy_id struct
1122 {kPadBytes, 0}, // up to NLMSG_ALIGNTO pad bytes of padding
manojboopathi8707f232018-01-02 14:45:47 -08001123 {&xfrmmark, 0}, // adjust size if xfrm mark is present
1124 {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
ludi771b8002017-11-20 15:09:05 -08001125 };
1126
1127 int len = iov[USERPOLICYID].iov_len = fillUserPolicyId(record, direction, &policyid);
1128 iov[USERPOLICYID_PAD].iov_len = NLMSG_ALIGN(len) - len;
1129
Di Lu2ccb3e52018-01-03 16:19:20 -08001130 len = iov[MARK].iov_len = fillNlAttrXfrmMark(record, &xfrmmark);
1131 iov[MARK_PAD].iov_len = NLA_ALIGN(len) - len;
1132
ludi771b8002017-11-20 15:09:05 -08001133 return sock.sendMessage(XFRM_MSG_DELPOLICY, NETLINK_REQUEST_FLAGS, 0, &iov);
1134}
1135
Nathan Haroldda54f122018-01-09 16:42:57 -08001136int XfrmController::fillTransportModeUserSpInfo(const XfrmSaInfo& record, XfrmDirection direction,
Nathan Harold1a371532017-01-30 12:30:48 -08001137 xfrm_userpolicy_info* usersp) {
ludi771b8002017-11-20 15:09:05 -08001138 fillXfrmSelector(record, &usersp->sel);
Nathan Harold1a371532017-01-30 12:30:48 -08001139 fillXfrmLifetimeDefaults(&usersp->lft);
1140 fillXfrmCurLifetimeDefaults(&usersp->curlft);
Nathan Harold420ceac2017-04-05 19:36:59 -07001141 /* if (index) index & 0x3 == dir -- must be true
1142 * xfrm_user.c:verify_newpolicy_info() */
Nathan Harold1a371532017-01-30 12:30:48 -08001143 usersp->index = 0;
Nathan Haroldda54f122018-01-09 16:42:57 -08001144 usersp->dir = static_cast<uint8_t>(direction);
Nathan Harold1a371532017-01-30 12:30:48 -08001145 usersp->action = XFRM_POLICY_ALLOW;
1146 usersp->flags = XFRM_POLICY_LOCALOK;
1147 usersp->share = XFRM_SHARE_UNIQUE;
1148 return sizeof(*usersp);
1149}
1150
1151int XfrmController::fillUserTemplate(const XfrmSaInfo& record, xfrm_user_tmpl* tmpl) {
1152 tmpl->id.daddr = record.dstAddr;
1153 tmpl->id.spi = record.spi;
1154 tmpl->id.proto = IPPROTO_ESP;
1155
1156 tmpl->family = record.addrFamily;
1157 tmpl->saddr = record.srcAddr;
1158 tmpl->reqid = record.transformId;
1159 tmpl->mode = static_cast<uint8_t>(record.mode);
1160 tmpl->share = XFRM_SHARE_UNIQUE;
1161 tmpl->optional = 0; // if this is true, then a failed state lookup will be considered OK:
1162 // http://lxr.free-electrons.com/source/net/xfrm/xfrm_policy.c#L1492
1163 tmpl->aalgos = ALGO_MASK_AUTH_ALL; // TODO: if there's a bitmask somewhere of
1164 // algos, we should find it and apply it.
1165 // I can't find one.
1166 tmpl->ealgos = ALGO_MASK_CRYPT_ALL; // TODO: if there's a bitmask somewhere...
ludi771b8002017-11-20 15:09:05 -08001167 return sizeof(xfrm_user_tmpl*);
Nathan Harold1a371532017-01-30 12:30:48 -08001168}
1169
ludi771b8002017-11-20 15:09:05 -08001170int XfrmController::fillNlAttrUserTemplate(const XfrmSaInfo& record, nlattr_user_tmpl* tmpl) {
1171 fillUserTemplate(record, &tmpl->tmpl);
1172
1173 int len = NLA_HDRLEN + sizeof(xfrm_user_tmpl);
1174 fillXfrmNlaHdr(&tmpl->hdr, XFRMA_TMPL, len);
1175 return len;
1176}
1177
Di Lu2ccb3e52018-01-03 16:19:20 -08001178int XfrmController::fillNlAttrXfrmMark(const XfrmId& record, nlattr_xfrm_mark* mark) {
1179 mark->mark.v = record.mark.v; // set to 0 if it's not used
1180 mark->mark.m = record.mark.m; // set to 0 if it's not used
1181 int len = NLA_HDRLEN + sizeof(xfrm_mark);
1182 fillXfrmNlaHdr(&mark->hdr, XFRMA_MARK, len);
1183 return len;
1184}
1185
manojboopathi8707f232018-01-02 14:45:47 -08001186int XfrmController::fillNlAttrXfrmOutputMark(const __u32 output_mark_value,
1187 nlattr_xfrm_output_mark* output_mark) {
Benedict Wong96abf482018-01-22 13:56:41 -08001188 // Do not set if we were not given an output mark
1189 if (output_mark_value == 0) {
1190 return 0;
1191 }
1192
1193 output_mark->outputMark = output_mark_value;
1194 int len = NLA_HDRLEN + sizeof(__u32);
1195 fillXfrmNlaHdr(&output_mark->hdr, XFRMA_OUTPUT_MARK, len);
1196 return len;
1197}
1198
ludi771b8002017-11-20 15:09:05 -08001199int XfrmController::fillUserPolicyId(const XfrmSaInfo& record, XfrmDirection direction,
1200 xfrm_userpolicy_id* usersp) {
1201 // For DELPOLICY, when index is absent, selector is needed to match the policy
1202 fillXfrmSelector(record, &usersp->sel);
1203 usersp->dir = static_cast<uint8_t>(direction);
1204 return sizeof(*usersp);
1205}
1206
manojboopathi8707f232018-01-02 14:45:47 -08001207int XfrmController::addVirtualTunnelInterface(const std::string& deviceName,
1208 const std::string& localAddress,
1209 const std::string& remoteAddress, int32_t ikey,
1210 int32_t okey, bool isUpdate) {
1211 ALOGD("XfrmController::%s, line=%d", __FUNCTION__, __LINE__);
1212 ALOGD("deviceName=%s", deviceName.c_str());
1213 ALOGD("localAddress=%s", localAddress.c_str());
1214 ALOGD("remoteAddress=%s", remoteAddress.c_str());
1215 ALOGD("ikey=%0.8x", ikey);
1216 ALOGD("okey=%0.8x", okey);
1217 ALOGD("isUpdate=%d", isUpdate);
1218
1219 if (deviceName.empty() || localAddress.empty() || remoteAddress.empty()) {
1220 return EINVAL;
1221 }
1222
1223 const char* INFO_KIND_VTI6 = "vti6";
1224 const char* INFO_KIND_VTI = "vti";
1225 uint8_t PADDING_BUFFER[] = {0, 0, 0, 0};
1226
1227 // Find address family.
1228 uint8_t remAddr[sizeof(in6_addr)];
1229
1230 StatusOr<uint16_t> statusOrRemoteFam = convertStringAddress(remoteAddress, remAddr);
1231 if (!isOk(statusOrRemoteFam)) {
1232 return statusOrRemoteFam.status().code();
1233 }
1234
1235 uint8_t locAddr[sizeof(in6_addr)];
1236 StatusOr<uint16_t> statusOrLocalFam = convertStringAddress(localAddress, locAddr);
1237 if (!isOk(statusOrLocalFam)) {
1238 return statusOrLocalFam.status().code();
1239 }
1240
1241 if (statusOrLocalFam.value() != statusOrRemoteFam.value()) {
1242 return EINVAL;
1243 }
1244
1245 uint16_t family = statusOrLocalFam.value();
1246
1247 ifinfomsg ifInfoMsg{};
1248
1249 // Construct IFLA_IFNAME
1250 nlattr iflaIfName;
1251 char iflaIfNameStrValue[deviceName.length() + 1];
1252 size_t iflaIfNameLength =
1253 strlcpy(iflaIfNameStrValue, deviceName.c_str(), sizeof(iflaIfNameStrValue));
1254 size_t iflaIfNamePad = fillNlAttr(IFLA_IFNAME, iflaIfNameLength, &iflaIfName);
1255
1256 // Construct IFLA_INFO_KIND
1257 // Constants "vti6" and "vti" enable the kernel to call different code paths,
1258 // (ip_tunnel.c, ip6_tunnel), based on the family.
1259 const std::string infoKindValue = (family == AF_INET6) ? INFO_KIND_VTI6 : INFO_KIND_VTI;
1260 nlattr iflaIfInfoKind;
1261 char infoKindValueStrValue[infoKindValue.length() + 1];
1262 size_t iflaIfInfoKindLength =
1263 strlcpy(infoKindValueStrValue, infoKindValue.c_str(), sizeof(infoKindValueStrValue));
1264 size_t iflaIfInfoKindPad = fillNlAttr(IFLA_INFO_KIND, iflaIfInfoKindLength, &iflaIfInfoKind);
1265
1266 // Construct IFLA_VTI_LOCAL
1267 nlattr iflaVtiLocal;
1268 uint8_t binaryLocalAddress[sizeof(in6_addr)];
1269 size_t iflaVtiLocalPad =
1270 fillNlAttrIpAddress(IFLA_VTI_LOCAL, family, localAddress, &iflaVtiLocal,
1271 netdutils::makeSlice(binaryLocalAddress));
1272
1273 // Construct IFLA_VTI_REMOTE
1274 nlattr iflaVtiRemote;
1275 uint8_t binaryRemoteAddress[sizeof(in6_addr)];
1276 size_t iflaVtiRemotePad =
1277 fillNlAttrIpAddress(IFLA_VTI_REMOTE, family, remoteAddress, &iflaVtiRemote,
1278 netdutils::makeSlice(binaryRemoteAddress));
1279
1280 // Construct IFLA_VTI_OKEY
1281 nlattr iflaVtiIKey;
1282 uint32_t iKeyValue;
1283 size_t iflaVtiIKeyPad = fillNlAttrU32(IFLA_VTI_IKEY, ikey, &iflaVtiIKey, &iKeyValue);
1284
1285 // Construct IFLA_VTI_IKEY
1286 nlattr iflaVtiOKey;
1287 uint32_t oKeyValue;
1288 size_t iflaVtiOKeyPad = fillNlAttrU32(IFLA_VTI_OKEY, okey, &iflaVtiOKey, &oKeyValue);
1289
1290 int iflaInfoDataPayloadLength = iflaVtiLocal.nla_len + iflaVtiLocalPad + iflaVtiRemote.nla_len +
1291 iflaVtiRemotePad + iflaVtiIKey.nla_len + iflaVtiIKeyPad +
1292 iflaVtiOKey.nla_len + iflaVtiOKeyPad;
1293
1294 // Construct IFLA_INFO_DATA
1295 nlattr iflaInfoData;
1296 size_t iflaInfoDataPad = fillNlAttr(IFLA_INFO_DATA, iflaInfoDataPayloadLength, &iflaInfoData);
1297
1298 // Construct IFLA_LINKINFO
1299 nlattr iflaLinkInfo;
1300 size_t iflaLinkInfoPad = fillNlAttr(IFLA_LINKINFO,
1301 iflaInfoData.nla_len + iflaInfoDataPad +
1302 iflaIfInfoKind.nla_len + iflaIfInfoKindPad,
1303 &iflaLinkInfo);
1304
1305 iovec iov[] = {
1306 {NULL, 0},
1307 {&ifInfoMsg, sizeof(ifInfoMsg)},
1308
1309 {&iflaIfName, sizeof(iflaIfName)},
1310 {iflaIfNameStrValue, iflaIfNameLength},
1311 {&PADDING_BUFFER, iflaIfNamePad},
1312
1313 {&iflaLinkInfo, sizeof(iflaLinkInfo)},
1314
1315 {&iflaIfInfoKind, sizeof(iflaIfInfoKind)},
1316 {infoKindValueStrValue, iflaIfInfoKindLength},
1317 {&PADDING_BUFFER, iflaIfInfoKindPad},
1318
1319 {&iflaInfoData, sizeof(iflaInfoData)},
1320
1321 {&iflaVtiLocal, sizeof(iflaVtiLocal)},
1322 {&binaryLocalAddress, (family == AF_INET) ? sizeof(in_addr) : sizeof(in6_addr)},
1323 {&PADDING_BUFFER, iflaVtiLocalPad},
1324
1325 {&iflaVtiRemote, sizeof(iflaVtiRemote)},
1326 {&binaryRemoteAddress, (family == AF_INET) ? sizeof(in_addr) : sizeof(in6_addr)},
1327 {&PADDING_BUFFER, iflaVtiRemotePad},
1328
1329 {&iflaVtiIKey, sizeof(iflaVtiIKey)},
1330 {&iKeyValue, sizeof(iKeyValue)},
1331 {&PADDING_BUFFER, iflaVtiIKeyPad},
1332
1333 {&iflaVtiOKey, sizeof(iflaVtiOKey)},
1334 {&oKeyValue, sizeof(oKeyValue)},
1335 {&PADDING_BUFFER, iflaVtiOKeyPad},
1336
1337 {&PADDING_BUFFER, iflaInfoDataPad},
1338
1339 {&PADDING_BUFFER, iflaLinkInfoPad},
1340 };
1341
1342 uint16_t action = RTM_NEWLINK;
1343 uint16_t flags = NLM_F_REQUEST | NLM_F_ACK;
1344
1345 if (!isUpdate) {
1346 flags |= NLM_F_EXCL | NLM_F_CREATE;
1347 }
1348
1349 int ret = sendNetlinkRequest(action, flags, iov, ARRAY_SIZE(iov), nullptr);
1350 if (ret) {
1351 ALOGE("Error in %s virtual tunnel interface. Error Code: %d",
1352 isUpdate ? "updating" : "adding", ret);
1353 }
1354 return ret;
1355}
1356
1357int XfrmController::removeVirtualTunnelInterface(const std::string& deviceName) {
1358 ALOGD("XfrmController::%s, line=%d", __FUNCTION__, __LINE__);
1359 ALOGD("deviceName=%s", deviceName.c_str());
1360
1361 if (deviceName.empty()) {
1362 return EINVAL;
1363 }
1364
1365 uint8_t PADDING_BUFFER[] = {0, 0, 0, 0};
1366
1367 ifinfomsg ifInfoMsg{};
1368 nlattr iflaIfName;
1369 char iflaIfNameStrValue[deviceName.length() + 1];
1370 size_t iflaIfNameLength =
1371 strlcpy(iflaIfNameStrValue, deviceName.c_str(), sizeof(iflaIfNameStrValue));
1372 size_t iflaIfNamePad = fillNlAttr(IFLA_IFNAME, iflaIfNameLength, &iflaIfName);
1373
1374 iovec iov[] = {
1375 {NULL, 0},
1376 {&ifInfoMsg, sizeof(ifInfoMsg)},
1377
1378 {&iflaIfName, sizeof(iflaIfName)},
1379 {iflaIfNameStrValue, iflaIfNameLength},
1380 {&PADDING_BUFFER, iflaIfNamePad},
1381 };
1382
1383 uint16_t action = RTM_DELLINK;
1384 uint16_t flags = NLM_F_REQUEST | NLM_F_ACK;
1385
1386 int ret = sendNetlinkRequest(action, flags, iov, ARRAY_SIZE(iov), nullptr);
1387 if (ret) {
1388 ALOGE("Error in removing virtual tunnel interface %s. Error Code: %d", iflaIfNameStrValue,
1389 ret);
1390 }
1391 return ret;
1392}
ludi771b8002017-11-20 15:09:05 -08001393
Nathan Harold1a371532017-01-30 12:30:48 -08001394} // namespace net
1395} // namespace android