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 // This program is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU Affero General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Affero General Public License for more details.
14 //
15 // You should have received a copy of the GNU Affero General Public License
16 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 //
18 #include <string>
19 #include <cstring>
20 #include <iostream>
21 #include "spdlog/spdlog.h"
22 #include <netlink/netlink.h>
23 #include <netlink/attr.h>
24 #include <netlink/msg.h>
25 #include <linux/rtnetlink.h>
26 #include <linux/in.h>
27 #include <linux/xfrm.h>
28 #include <linux/ipsec.h>
29 #include <arpa/inet.h>
30 #include "IpSec.h"
31 #include <boost/algorithm/hex.hpp>
32 
33 namespace LibFlute::IpSec {
34  void configure_policy(uint32_t spi, const std::string& dest_address, Direction direction)
35  {
36  struct nl_sock *sk;
37  struct nl_msg *msg;
38 
39  struct xfrm_userpolicy_info xpinfo = {};
40  xpinfo.lft.soft_byte_limit = XFRM_INF;
41  xpinfo.lft.hard_byte_limit = XFRM_INF;
42  xpinfo.lft.soft_packet_limit = XFRM_INF;
43  xpinfo.lft.hard_packet_limit = XFRM_INF;
44  xpinfo.dir = (direction == Direction::In) ? XFRM_POLICY_IN : XFRM_POLICY_OUT;
45 
46  xpinfo.sel.family = AF_INET;
47  xpinfo.sel.saddr.a4 = INADDR_ANY;
48  xpinfo.sel.daddr.a4 = inet_addr(dest_address.c_str());
49  xpinfo.sel.prefixlen_d = 32;
50 
51  struct xfrm_user_tmpl tmpl = {};
52  tmpl.id.daddr.a4 = inet_addr(dest_address.c_str());
53  tmpl.id.spi = htonl(spi);
54  tmpl.id.proto = IPPROTO_ESP;
55  tmpl.saddr.a4 = INADDR_ANY;
56  tmpl.reqid = spi;
57  tmpl.mode = XFRM_MODE_TRANSPORT;
58  tmpl.aalgos = (~(__u32)0);
59  tmpl.ealgos = (~(__u32)0);
60  tmpl.calgos = (~(__u32)0);
61  tmpl.family = AF_INET;
62 
63  msg = nlmsg_alloc_simple(XFRM_MSG_UPDPOLICY, 0);
64  nlmsg_append(msg, &xpinfo, sizeof(xpinfo), NLMSG_ALIGNTO);
65  nla_put(msg, XFRMA_TMPL, sizeof(tmpl), &tmpl);
66 
67  sk = nl_socket_alloc();
68  nl_connect(sk, NETLINK_XFRM);
69  nl_send_auto(sk, msg);
70  nlmsg_free(msg);
71  }
72  void configure_state(uint32_t spi, const std::string& dest_address, Direction direction, const std::string& key)
73  {
74  struct nl_sock *sk;
75  struct nl_msg *msg;
76 
77  struct xfrm_usersa_info xsinfo = {};
78 
79  xsinfo.sel.family = AF_INET;
80  xsinfo.sel.saddr.a4 = INADDR_ANY;
81  xsinfo.sel.daddr.a4 = inet_addr(dest_address.c_str());
82  xsinfo.sel.prefixlen_d = 32;
83 
84  xsinfo.id.daddr.a4 = inet_addr(dest_address.c_str());
85  xsinfo.id.spi = htonl(spi);
86  xsinfo.id.proto = IPPROTO_ESP;
87 
88  xsinfo.saddr.a4 = INADDR_ANY;
89 
90  xsinfo.lft.soft_byte_limit = XFRM_INF;
91  xsinfo.lft.hard_byte_limit = XFRM_INF;
92  xsinfo.lft.soft_packet_limit = XFRM_INF;
93  xsinfo.lft.hard_packet_limit = XFRM_INF;
94 
95  xsinfo.reqid = spi;
96  xsinfo.family = AF_INET;
97  xsinfo.mode = XFRM_MODE_TRANSPORT;
98 
99  struct {
100  struct xfrm_algo xa;
101  char buf[512];
102  } algo = {};
103 
104  std::vector<char> binary_key;
105  for (unsigned int i = 0; i < key.length(); i += 2) {
106  binary_key.emplace_back((char)strtol(key.substr(i, 2).c_str(), nullptr, 16));
107  }
108  if (binary_key.size() > 512) {
109  throw "Key is too long";
110  }
111  strcpy(algo.xa.alg_name, "aes");
112  algo.xa.alg_key_len = binary_key.size() * 8;
113  memcpy(algo.buf, &binary_key[0], binary_key.size());
114 
115  msg = nlmsg_alloc_simple(XFRM_MSG_NEWSA, 0);
116  nlmsg_append(msg, &xsinfo, sizeof(xsinfo), NLMSG_ALIGNTO);
117  nla_put(msg, XFRMA_ALG_CRYPT, sizeof(algo), &algo);
118 
119  sk = nl_socket_alloc();
120  nl_connect(sk, NETLINK_XFRM);
121  nl_send_auto(sk, msg);
122  nlmsg_free(msg);
123  }
124 
125  void enable_esp(uint32_t spi, const std::string& dest_address, Direction direction, const std::string& key)
126  {
127  configure_state(spi, dest_address, direction, key);
128  configure_policy(spi, dest_address, direction);
129  }
130 };
void configure_policy(uint32_t spi, const std::string &dest_address, Direction direction)
Definition: IpSec.cpp:34
void enable_esp(uint32_t spi, const std::string &dest_address, Direction direction, const std::string &key)
Definition: IpSec.cpp:125
void configure_state(uint32_t spi, const std::string &dest_address, Direction direction, const std::string &key)
Definition: IpSec.cpp:72