libflute
IpSec.cpp
Go to the documentation of this file.
1 // libflute - FLUTE/ALC library
2 //
3 // Copyright (C) 2021 Klaus Kühnhammer (Österreichische Rundfunksender GmbH & Co KG)
4 //
5 // Licensed under the License terms and conditions for use, reproduction, and
6 // distribution of 5G-MAG software (the “License”). You may not use this file
7 // except in compliance with the License. You may obtain a copy of the License at
8 // https://www.5g-mag.com/reference-tools. Unless required by applicable law or
9 // agreed to in writing, software distributed under the License is distributed on
10 // an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 // or implied.
12 //
13 // See the License for the specific language governing permissions and limitations
14 // under the License.
15 //
16 #include <string>
17 #include <cstring>
18 #include <iostream>
19 #include "spdlog/spdlog.h"
20 #include <netlink/netlink.h>
21 #include <netlink/attr.h>
22 #include <netlink/msg.h>
23 #include <linux/rtnetlink.h>
24 #include <linux/in.h>
25 #include <linux/xfrm.h>
26 #include <linux/ipsec.h>
27 #include <arpa/inet.h>
28 #include "IpSec.h"
29 #include <boost/algorithm/hex.hpp>
30 
31 namespace LibFlute::IpSec {
32  void configure_policy(uint32_t spi, const std::string& dest_address, Direction direction)
33  {
34  struct nl_sock *sk;
35  struct nl_msg *msg;
36 
37  struct xfrm_userpolicy_info xpinfo = {};
38  xpinfo.lft.soft_byte_limit = XFRM_INF;
39  xpinfo.lft.hard_byte_limit = XFRM_INF;
40  xpinfo.lft.soft_packet_limit = XFRM_INF;
41  xpinfo.lft.hard_packet_limit = XFRM_INF;
42  xpinfo.dir = (direction == Direction::In) ? XFRM_POLICY_IN : XFRM_POLICY_OUT;
43 
44  xpinfo.sel.family = AF_INET;
45  xpinfo.sel.saddr.a4 = INADDR_ANY;
46  xpinfo.sel.daddr.a4 = inet_addr(dest_address.c_str());
47  xpinfo.sel.prefixlen_d = 32;
48 
49  struct xfrm_user_tmpl tmpl = {};
50  tmpl.id.daddr.a4 = inet_addr(dest_address.c_str());
51  tmpl.id.spi = htonl(spi);
52  tmpl.id.proto = IPPROTO_ESP;
53  tmpl.saddr.a4 = INADDR_ANY;
54  tmpl.reqid = spi;
55  tmpl.mode = XFRM_MODE_TRANSPORT;
56  tmpl.aalgos = (~(__u32)0);
57  tmpl.ealgos = (~(__u32)0);
58  tmpl.calgos = (~(__u32)0);
59  tmpl.family = AF_INET;
60 
61  msg = nlmsg_alloc_simple(XFRM_MSG_UPDPOLICY, 0);
62  nlmsg_append(msg, &xpinfo, sizeof(xpinfo), NLMSG_ALIGNTO);
63  nla_put(msg, XFRMA_TMPL, sizeof(tmpl), &tmpl);
64 
65  sk = nl_socket_alloc();
66  nl_connect(sk, NETLINK_XFRM);
67  nl_send_auto(sk, msg);
68  nlmsg_free(msg);
69  }
70  void configure_state(uint32_t spi, const std::string& dest_address, Direction direction, const std::string& key)
71  {
72  struct nl_sock *sk;
73  struct nl_msg *msg;
74 
75  struct xfrm_usersa_info xsinfo = {};
76 
77  xsinfo.sel.family = AF_INET;
78  xsinfo.sel.saddr.a4 = INADDR_ANY;
79  xsinfo.sel.daddr.a4 = inet_addr(dest_address.c_str());
80  xsinfo.sel.prefixlen_d = 32;
81 
82  xsinfo.id.daddr.a4 = inet_addr(dest_address.c_str());
83  xsinfo.id.spi = htonl(spi);
84  xsinfo.id.proto = IPPROTO_ESP;
85 
86  xsinfo.saddr.a4 = INADDR_ANY;
87 
88  xsinfo.lft.soft_byte_limit = XFRM_INF;
89  xsinfo.lft.hard_byte_limit = XFRM_INF;
90  xsinfo.lft.soft_packet_limit = XFRM_INF;
91  xsinfo.lft.hard_packet_limit = XFRM_INF;
92 
93  xsinfo.reqid = spi;
94  xsinfo.family = AF_INET;
95  xsinfo.mode = XFRM_MODE_TRANSPORT;
96 
97 
98  std::vector<char> binary_key;
99  for (unsigned int i = 0; i < key.length(); i += 2) {
100  binary_key.emplace_back((char)strtol(key.substr(i, 2).c_str(), nullptr, 16));
101  }
102  if (binary_key.size() > 512) {
103  throw "Key is too long";
104  }
105  size_t algo_size = sizeof(struct xfrm_algo) + binary_key.size();
106  void *algo_mem = std::malloc(algo_size);
107  struct xfrm_algo *algo = new(algo_mem) struct xfrm_algo;
108 
109  strcpy(algo->alg_name, "aes");
110  algo->alg_key_len = binary_key.size() * 8;
111  memcpy(algo->alg_key, &binary_key[0], binary_key.size());
112 
113  msg = nlmsg_alloc_simple(XFRM_MSG_NEWSA, 0);
114  nlmsg_append(msg, &xsinfo, sizeof(xsinfo), NLMSG_ALIGNTO);
115  nla_put(msg, XFRMA_ALG_CRYPT, algo_size, algo);
116 
117  sk = nl_socket_alloc();
118  nl_connect(sk, NETLINK_XFRM);
119  nl_send_auto(sk, msg);
120  nlmsg_free(msg);
121  std::free(algo);
122  }
123 
124  void enable_esp(uint32_t spi, const std::string& dest_address, Direction direction, const std::string& key)
125  {
126  configure_state(spi, dest_address, direction, key);
127  configure_policy(spi, dest_address, direction);
128  }
129 };
void configure_policy(uint32_t spi, const std::string &dest_address, Direction direction)
Definition: IpSec.cpp:32
void enable_esp(uint32_t spi, const std::string &dest_address, Direction direction, const std::string &key)
Definition: IpSec.cpp:124
void configure_state(uint32_t spi, const std::string &dest_address, Direction direction, const std::string &key)
Definition: IpSec.cpp:70