Big code refactoring #10

Merged
Sirherobrine23 merged 15 commits from code_refactoring into main 2024-03-15 04:08:27 +00:00
7 changed files with 2175 additions and 6 deletions
Showing only changes of commit d094b5d546 - Show all commits

@ -186,10 +186,10 @@ void wgKeys::generatePreshared(wg_key preshared_key) {
size_t ret, i; size_t ret, i;
int fd; int fd;
fd = open("/dev/urandom", O_RDONLY); fd = open("/dev/urandom", O_RDONLY);
assert(fd >= 0); if (fd <= 0);
for (i = 0; i < sizeof(wg_key); i += ret) { for (i = 0; i < sizeof(wg_key); i += ret) {
ret = read(fd, preshared_key + i, sizeof(wg_key) - i); ret = read(fd, preshared_key + i, sizeof(wg_key) - i);
assert(ret > 0); if (ret < 0);
} }
close(fd); close(fd);
return; return;

@ -0,0 +1,275 @@
#include "wginterface.hh"
#include "genKey/wgkeys.hh"
extern "C" {
#include "wireguard.h"
}
#include <string>
#include <ifaddrs.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <time.h>
#include <unistd.h>
std::string getWireguardVersion() {
return "Kernel";
}
void WireguardDevices::getInterfaces() {
size_t len; char *device_name, *devicesList = wg_list_device_names();
if (!devicesList) throw std::string("Unable to get device names");
// Clear list
this->clear();
// Set new devices
for (device_name = devicesList, len = 0; (len = strlen(device_name)); device_name += len + 1) this->push_back(std::string(device_name));
// Free memory
free(devicesList);
}
void WireguardDevices::deleteInterface(std::string wgName) {
// Check if exist, if not skip
if (this->exist(wgName)) {
int status = wg_del_device(wgName.c_str());
if (status < 0) throw std::string("Cannot delete interface, code: ").append(std::to_string(status));
}
}
void WireguardConfig::getWireguardConfig() {
if (this->name.length() == 0) throw std::string("Set wireguard name!");
else if (this->name.length() > IFNAMSIZ) throw std::string("Wireguard interface name is long, max name length is ").append(std::to_string(IFNAMSIZ));
else if (!(WireguardDevices().exist(this->name))) throw std::string("Wireguard interface not exist");
int status; wg_device *devConfig; wg_peer *peer;
if ((status = wg_get_device(&devConfig, this->name.c_str())) < 0) throw std::string("It was not possible to get the Wireguard interface settings, code: ").append(std::to_string(status));
if (devConfig->flags & WGDEVICE_HAS_PRIVATE_KEY) privateKey = wgKeys::toString(devConfig->private_key);
if (devConfig->flags & WGDEVICE_HAS_PUBLIC_KEY) publicKey = wgKeys::toString(devConfig->public_key);
if (devConfig->flags & WGDEVICE_HAS_LISTEN_PORT) portListen = devConfig->listen_port;
auto HostAdresses = [](bool addPort, const sockaddr* addr) -> std::string {
char host[4096 + 1], service[512 + 1];
static char buf[sizeof(host) + sizeof(service) + 4];
memset(buf, 0, sizeof(buf));
int ret;
socklen_t addr_len = 0;
if (addr->sa_family == AF_INET) addr_len = sizeof(struct sockaddr_in);
else if (addr->sa_family == AF_INET6) addr_len = sizeof(struct sockaddr_in6);
ret = getnameinfo(addr, addr_len, host, sizeof(host), service, sizeof(service), NI_DGRAM | NI_NUMERICSERV | NI_NUMERICHOST);
if (ret) {
strncpy(buf, gai_strerror(ret), sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
} else {
if (addPort) snprintf(buf, sizeof(buf), (addr->sa_family == AF_INET6 && strchr(host, ':')) ? "[%s]:%s" : "%s:%s", host, service);
else snprintf(buf, sizeof(buf), "%s", host);
}
return std::string(buf);
};
ifaddrs* ptr_ifaddrs = nullptr;
if(getifaddrs(&ptr_ifaddrs) > 0) {
for (ifaddrs* ptr_entry = ptr_ifaddrs; ptr_entry != nullptr; ptr_entry = ptr_entry->ifa_next) {
if (ptr_entry->ifa_addr == nullptr) continue;
else if (strcmp(ptr_entry->ifa_name, this->name.c_str()) != 0) continue;
else if (ptr_entry->ifa_addr->sa_family == AF_INET) this->interfaceAddress.addIPMask(HostAdresses(false, ptr_entry->ifa_addr));
else if (ptr_entry->ifa_addr->sa_family == AF_INET6) this->interfaceAddress.addIPMask(HostAdresses(false, ptr_entry->ifa_addr));
}
freeifaddrs(ptr_ifaddrs);
}
for ((peer) = (devConfig)->first_peer; (peer); (peer) = (peer)->next_peer) {
auto PeerConfig = Peer();
if (peer->flags & WGPEER_HAS_PRESHARED_KEY) PeerConfig.presharedKey = wgKeys::toString(peer->preshared_key);
if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL) PeerConfig.keepInterval = peer->persistent_keepalive_interval;
if (peer->endpoint.addr.sa_family == AF_INET||peer->endpoint.addr.sa_family == AF_INET6) PeerConfig.endpoint = HostAdresses(true, &peer->endpoint.addr);
PeerConfig.lastHandshake = peer->last_handshake_time.tv_sec*1000;
PeerConfig.rxBytes = peer->rx_bytes;
PeerConfig.txBytes = peer->tx_bytes;
if (peer->first_allowedip) {
wg_allowedip *allowedip;
for ((allowedip) = (peer)->first_allowedip; (allowedip); (allowedip) = (allowedip)->next_allowedip) {
static char buf[INET6_ADDRSTRLEN + 1];
memset(buf, 0, INET6_ADDRSTRLEN + 1);
if (allowedip->family == AF_INET) inet_ntop(AF_INET, &allowedip->ip4, buf, INET6_ADDRSTRLEN);
else if (allowedip->family == AF_INET6) inet_ntop(AF_INET6, &allowedip->ip6, buf, INET6_ADDRSTRLEN);
PeerConfig.allowedIPs.push_back(std::string(buf).append("/").append(std::to_string(allowedip->cidr)));
}
}
this->Peers[wgKeys::toString(peer->public_key)] = PeerConfig;
}
}
void WireguardConfig::setWireguardConfig() {
int status;
if (this->name.length() == 0) throw std::string("Set wireguard name!");
else if (this->name.length() > IFNAMSIZ) throw std::string("Wireguard interface name is long, max name length is ").append(std::to_string(IFNAMSIZ));
else if (!(WireguardDevices().exist(this->name)) && (status = wg_add_device(this->name.c_str())) < 0) throw std::string("Unable to create Wireguard interface, code: ").append(std::to_string(status));
if (this->privateKey.length() != Base64WgKeyLength) throw std::string("Set Wireguard interface private key!");
auto wgConfig = (wg_device*)malloc(sizeof(wg_device));
if (!wgConfig) throw std::string("Cannot alloc memory to set interface configuration!");
strncpy(wgConfig->name, this->name.c_str(), this->name.length());
wgConfig->flags = wg_device_flags::WGDEVICE_HAS_PRIVATE_KEY;
wgKeys::stringToKey(wgConfig->private_key, this->privateKey);
if (this->replacePeers) wgConfig->flags = (wg_device_flags)(wgConfig->flags|wg_device_flags::WGDEVICE_REPLACE_PEERS);
if (this->publicKey.length() == Base64WgKeyLength) {
wgConfig->flags = (wg_device_flags)(wgConfig->flags|wg_device_flags::WGDEVICE_HAS_PUBLIC_KEY);
wgKeys::stringToKey(wgConfig->public_key, this->publicKey);
}
if (this->portListen >= 0) {
wgConfig->flags = (wg_device_flags)(wgConfig->flags|wg_device_flags::WGDEVICE_HAS_LISTEN_PORT);
wgConfig->listen_port = this->portListen;
}
if (this->fwmark >= 0) {
wgConfig->flags = (wg_device_flags)(wgConfig->flags|wg_device_flags::WGDEVICE_HAS_FWMARK);
wgConfig->fwmark = this->fwmark;
}
for (auto &PeerConfig : this->Peers) {
wg_peer* peer;
peer = (wg_peer*)malloc(sizeof(wg_peer));
peer->flags = wg_peer_flags::WGPEER_HAS_PUBLIC_KEY;
wgKeys::stringToKey(peer->public_key, PeerConfig.first);
if (PeerConfig.second.removeMe) peer->flags = (wg_peer_flags)(peer->flags|wg_peer_flags::WGPEER_REMOVE_ME);
else {
if (PeerConfig.second.presharedKey.length() == Base64WgKeyLength) {
peer->flags = (wg_peer_flags)(peer->flags|wg_peer_flags::WGPEER_HAS_PRESHARED_KEY);
wgKeys::stringToKey(peer->preshared_key, PeerConfig.second.presharedKey);
}
if (PeerConfig.second.keepInterval > 0) {
peer->flags = (wg_peer_flags)(peer->flags|wg_peer_flags::WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL);
peer->persistent_keepalive_interval = PeerConfig.second.keepInterval;
}
if (PeerConfig.second.endpoint.length() > 0) {
sockaddr endpoint; int ret, retries;
char *begin, *end, *Endpoint = strdup(PeerConfig.second.endpoint.c_str());
if (Endpoint[0] == '[') {
begin = &Endpoint[1];
end = strchr(Endpoint, ']');
if (!end) {
for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { free(peer); }
free(wgConfig);
free(Endpoint);
throw std::string("Unable to find matching brace of endpoint");
return;
}
*end++ = '\0';
if (*end++ != ':' || !*end) {
for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { free(peer); }
free(wgConfig);
free(Endpoint);
throw std::string("Unable to find port of endpoint");
return;
}
} else {
begin = Endpoint;
end = strrchr(Endpoint, ':');
if (!end || !*(end + 1)) {
for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { free(peer); }
free(wgConfig);
free(Endpoint);
throw std::string("Unable to find port of endpoint");
}
*end++ = '\0';
}
addrinfo *resolved, hints = { ai_family: AF_UNSPEC, ai_socktype: SOCK_DGRAM, ai_protocol: IPPROTO_UDP };
for (unsigned int timeout = 1000000;; timeout = ((20000000) < (timeout * 6 / 5) ? (20000000) : (timeout * 6 / 5))) {
ret = getaddrinfo(begin, end, &hints, &resolved);
if (!ret) break;
if (ret == EAI_NONAME || ret == EAI_FAIL ||
#ifdef EAI_NODATA
ret == EAI_NODATA ||
#endif
(retries >= 0 && !retries--)) {
for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { free(peer); }
free(wgConfig);
free(Endpoint);
fprintf(stderr, "%s: `%s'\n", ret == EAI_SYSTEM ? strerror(errno) : gai_strerror(ret), PeerConfig.second.endpoint.c_str());
throw std::string("Unable to resolve endpoint");
return;
}
fprintf(stderr, "%s: `%s'. Trying again in %.2f seconds...\n", ret == EAI_SYSTEM ? strerror(errno) : gai_strerror(ret), PeerConfig.second.endpoint.c_str(), timeout / 1000000.0);
usleep(timeout);
}
if ((resolved->ai_family == AF_INET && resolved->ai_addrlen == sizeof(sockaddr_in)) || (resolved->ai_family == AF_INET6 && resolved->ai_addrlen == sizeof(sockaddr_in6))) {
memcpy(&endpoint, resolved->ai_addr, resolved->ai_addrlen);
memccpy(&peer->endpoint.addr, &endpoint, 0, sizeof(peer->endpoint.addr));
if (resolved->ai_family == AF_INET) {
peer->endpoint.addr4.sin_addr.s_addr = ((sockaddr_in *)&endpoint)->sin_addr.s_addr;
peer->endpoint.addr4.sin_port = ((sockaddr_in *)&endpoint)->sin_port;
peer->endpoint.addr4.sin_family = AF_INET;
} else {
peer->endpoint.addr6.sin6_addr = ((struct sockaddr_in6 *)&endpoint)->sin6_addr;
peer->endpoint.addr6.sin6_port = ((struct sockaddr_in6 *)&endpoint)->sin6_port;
peer->endpoint.addr6.sin6_family = AF_INET6;
}
} else {
freeaddrinfo(resolved);
for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { free(peer); }
free(wgConfig);
free(Endpoint);
throw std::string("Neither IPv4 nor IPv6 address found");
}
freeaddrinfo(resolved);
// Free memory
for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { free(peer); }
free(wgConfig);
free(Endpoint);
}
// Set allowed IPs
if (PeerConfig.second.allowedIPs.size() > 0) {
wg_allowedip *newAllowedIP;
peer->flags = (wg_peer_flags)(peer->flags|WGPEER_REPLACE_ALLOWEDIPS);
for (const auto &Ip : PeerConfig.second.allowedIPs.getIpParsed()) {
newAllowedIP = (wg_allowedip*)(malloc(sizeof(wg_allowedip)));
newAllowedIP->cidr = Ip.Mask;
if (Ip.Proto == 6 && inet_pton(AF_INET6, Ip.Address.c_str(), &newAllowedIP->ip6) == 1) newAllowedIP->family = AF_INET6;
else if (Ip.Proto == 4 && inet_pton(AF_INET, Ip.Address.c_str(), &newAllowedIP->ip4) == 1) newAllowedIP->family = AF_INET;
else {
free(newAllowedIP);
continue;
}
if (peer->first_allowedip) newAllowedIP->next_allowedip = peer->first_allowedip;
peer->first_allowedip = newAllowedIP;
}
}
}
if (wgConfig->first_peer) peer->next_peer = wgConfig->first_peer;
wgConfig->first_peer = peer;
}
// Set config
status = wg_set_device(wgConfig);
// Free memory
for (wg_peer* peer = wgConfig->first_peer; peer; peer = peer->next_peer) {
for (wg_allowedip *newAllowedIP = peer->first_allowedip; newAllowedIP; newAllowedIP = newAllowedIP->next_allowedip) free(newAllowedIP);
free(peer);
}
free(wgConfig);
// Return status to tool
if (status < 0) throw std::string("Unable to configure settings, code: ").append(std::to_string(status));
else {
this->interfaceAddress.SetInInterface(this->name);
}
}
void IpManeger::SetInInterface(std::string interfaceName) {
if (this->size() == 0) return;
}

1755
addon/linux/wireguard.c Normal file

File diff suppressed because it is too large Load Diff

105
addon/linux/wireguard.h Normal file

@ -0,0 +1,105 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/*
* Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
*/
#ifndef WIREGUARD_H
#define WIREGUARD_H
#include <net/if.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <time.h>
#include <stdint.h>
#include <stdbool.h>
typedef uint8_t wg_key[32];
typedef char wg_key_b64_string[((sizeof(wg_key) + 2) / 3) * 4 + 1];
/* Cross platform __kernel_timespec */
struct timespec64 {
int64_t tv_sec;
int64_t tv_nsec;
};
typedef struct wg_allowedip {
uint16_t family;
union {
struct in_addr ip4;
struct in6_addr ip6;
};
uint8_t cidr;
struct wg_allowedip *next_allowedip;
} wg_allowedip;
enum wg_peer_flags {
WGPEER_REMOVE_ME = 1U << 0,
WGPEER_REPLACE_ALLOWEDIPS = 1U << 1,
WGPEER_HAS_PUBLIC_KEY = 1U << 2,
WGPEER_HAS_PRESHARED_KEY = 1U << 3,
WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL = 1U << 4
};
typedef union wg_endpoint {
struct sockaddr addr;
struct sockaddr_in addr4;
struct sockaddr_in6 addr6;
} wg_endpoint;
typedef struct wg_peer {
enum wg_peer_flags flags;
wg_key public_key;
wg_key preshared_key;
wg_endpoint endpoint;
struct timespec64 last_handshake_time;
uint64_t rx_bytes, tx_bytes;
uint16_t persistent_keepalive_interval;
struct wg_allowedip *first_allowedip, *last_allowedip;
struct wg_peer *next_peer;
} wg_peer;
enum wg_device_flags {
WGDEVICE_REPLACE_PEERS = 1U << 0,
WGDEVICE_HAS_PRIVATE_KEY = 1U << 1,
WGDEVICE_HAS_PUBLIC_KEY = 1U << 2,
WGDEVICE_HAS_LISTEN_PORT = 1U << 3,
WGDEVICE_HAS_FWMARK = 1U << 4
};
typedef struct wg_device {
char name[IFNAMSIZ];
uint32_t ifindex;
enum wg_device_flags flags;
wg_key public_key;
wg_key private_key;
uint32_t fwmark;
uint16_t listen_port;
struct wg_peer *first_peer, *last_peer;
} wg_device;
#define wg_for_each_device_name(__names, __name, __len) for ((__name) = (__names), (__len) = 0; ((__len) = strlen(__name)); (__name) += (__len) + 1)
#define wg_for_each_peer(__dev, __peer) for ((__peer) = (__dev)->first_peer; (__peer); (__peer) = (__peer)->next_peer)
#define wg_for_each_allowedip(__peer, __allowedip) for ((__allowedip) = (__peer)->first_allowedip; (__allowedip); (__allowedip) = (__allowedip)->next_allowedip)
int wg_set_device(wg_device *dev);
int wg_get_device(wg_device **dev, const char *device_name);
int wg_add_device(const char *device_name);
int wg_del_device(const char *device_name);
void wg_free_device(wg_device *dev);
char *wg_list_device_names(void); /* first\0second\0third\0forth\0last\0\0 */
void wg_key_to_base64(wg_key_b64_string base64, const wg_key key);
int wg_key_from_base64(wg_key key, const wg_key_b64_string base64);
bool wg_key_is_zero(const wg_key key);
void wg_generate_public_key(wg_key public_key, const wg_key private_key);
void wg_generate_private_key(wg_key private_key);
void wg_generate_preshared_key(wg_key preshared_key);
#endif

@ -31,13 +31,42 @@ class WireguardDevices : public std::vector<std::string> {
} }
}; };
typedef struct IpReference {
std::string Address;
int Mask, Proto;
};
/** Maneger Interface IPs */ /** Maneger Interface IPs */
class IpManeger : public std::vector<std::string> { class IpManeger : public std::vector<std::string> {
public: public:
void SetInInterface(std::string interfaceName); void SetInInterface(std::string interfaceName);
void addIP(std::string ip) { void addIPMask(std::string ip) {
this->push_back(ip); IpReference xTop;
auto maskStart = ip.find("/");
auto isIPv6 = ip.find(":") != std::string::npos;
if (isIPv6) xTop.Mask = 128;
else xTop.Mask = 32;
if (maskStart == std::string::npos) xTop.Address = ip;
else {
xTop.Address = ip.substr(0, maskStart);
xTop.Mask = atoi(ip.substr(maskStart+1).c_str());
if (!isIPv6 && xTop.Mask > 32) throw std::string("Set valid mask to ipv4 address!");
}
xTop.Proto = isIPv6 ? 6 : 4;
this->push_back(xTop.Address.append("/").append(std::to_string(xTop.Mask)));
}
std::vector<IpReference> getIpParsed() {
std::vector<IpReference> xTops;
for (auto ipAddrr = this->begin(); ipAddrr != this->end(); ++ipAddrr) {
IpReference nTop;
auto maskStart = ipAddrr->find("/");
nTop.Address = ipAddrr->substr(0, maskStart);
nTop.Mask = atoi(ipAddrr->substr(maskStart+1).c_str());
xTops.push_back(nTop);
}
return xTops;
} }
}; };

@ -13,12 +13,17 @@ sources:
target: target:
linux: linux:
sources:
- "!addon/dummy/wginterface.cpp"
- "addon/linux/wginterface.cpp"
- "addon/linux/wireguard.c"
flags: flags:
- "!-fno-exceptions" - "!-fno-exceptions"
- "-fpermissive" - "-fpermissive"
- "-fexceptions" - "-fexceptions"
- "-w" - "-w"
- "-fpermissive" - "-fpermissive"
- "-fPIC"
macos: macos:
flags: flags:
- "!-fno-exceptions" - "!-fno-exceptions"