diff --git a/include/columnlynx/common/libsodium_wrapper.hpp b/include/columnlynx/common/libsodium_wrapper.hpp index 9ce7204..e39423b 100644 --- a/include/columnlynx/common/libsodium_wrapper.hpp +++ b/include/columnlynx/common/libsodium_wrapper.hpp @@ -47,9 +47,14 @@ namespace ColumnLynx::Utils { mPublicKey = pk; mPrivateKey = sk; + int r; // Convert to Curve25519 keys for encryption - crypto_sign_ed25519_pk_to_curve25519(mXPublicKey.data(), mPublicKey.data()); - crypto_sign_ed25519_sk_to_curve25519(mXPrivateKey.data(), mPrivateKey.data()); + r = crypto_sign_ed25519_pk_to_curve25519(mXPublicKey.data(), mPublicKey.data()); + r = crypto_sign_ed25519_sk_to_curve25519(mXPrivateKey.data(), mPrivateKey.data()); + + if (r != 0) { + throw std::runtime_error("Conversion of signing keys to encryption keys failed!"); + } } // Helper section diff --git a/include/columnlynx/common/net/session_registry.hpp b/include/columnlynx/common/net/session_registry.hpp index d4699ff..20939ba 100644 --- a/include/columnlynx/common/net/session_registry.hpp +++ b/include/columnlynx/common/net/session_registry.hpp @@ -122,9 +122,9 @@ namespace ColumnLynx::Net { if (mSessionIPs.find(candidateIP) == mSessionIPs.end()) { return candidateIP; } - - return 0; // Unavailable } + + return 0; // Unavailable } // Lock an IP as assigned to a specific session diff --git a/src/client/main.cpp b/src/client/main.cpp index f6da9cf..2f7ddd7 100644 --- a/src/client/main.cpp +++ b/src/client/main.cpp @@ -66,7 +66,7 @@ int main(int argc, char** argv) { WintunInitialize(); #endif - std::shared_ptr tun = std::make_shared("utun1"); + std::shared_ptr tun = std::make_shared("lynx0"); log("Using virtual interface: " + tun->getName()); LibSodiumWrapper sodiumWrapper = LibSodiumWrapper(); diff --git a/src/client/net/tcp/tcp_client.cpp b/src/client/net/tcp/tcp_client.cpp index 55c1457..201984a 100644 --- a/src/client/net/tcp/tcp_client.cpp +++ b/src/client/net/tcp/tcp_client.cpp @@ -196,7 +196,12 @@ namespace ColumnLynx::Net::TCP { // Convert the server's public key to Curve25519 for encryption AsymPublicKey serverXPubKey{}; - crypto_sign_ed25519_pk_to_curve25519(serverXPubKey.data(), mServerPublicKey); + int r = crypto_sign_ed25519_pk_to_curve25519(serverXPubKey.data(), mServerPublicKey); + if (r != 0) { + Utils::error("Failed to convert server signing key to encryption key! Killing connection."); + disconnect(); + return; + } // Generate AES key and send confirmation mConnectionAESKey = Utils::LibSodiumWrapper::generateRandom256Bit(); diff --git a/src/common/libsodium_wrapper.cpp b/src/common/libsodium_wrapper.cpp index 74bd906..8d7a8c0 100644 --- a/src/common/libsodium_wrapper.cpp +++ b/src/common/libsodium_wrapper.cpp @@ -16,9 +16,14 @@ namespace ColumnLynx::Utils { throw std::runtime_error("Failed to generate key pair"); } + int r; // Convert to Curve25519 keys for encryption - crypto_sign_ed25519_pk_to_curve25519(mXPublicKey.data(), mPublicKey.data()); - crypto_sign_ed25519_sk_to_curve25519(mXPrivateKey.data(), mPrivateKey.data()); + r = crypto_sign_ed25519_pk_to_curve25519(mXPublicKey.data(), mPublicKey.data()); + r = crypto_sign_ed25519_sk_to_curve25519(mXPrivateKey.data(), mPrivateKey.data()); + + if (r != 0) { + throw std::runtime_error("Conversion of signing keys to encryption keys failed!"); + } log("Libsodium initialized and keypair generated"); } diff --git a/src/common/utils.cpp b/src/common/utils.cpp index c873e22..eff056b 100644 --- a/src/common/utils.cpp +++ b/src/common/utils.cpp @@ -133,7 +133,7 @@ namespace ColumnLynx::Utils { std::unordered_map config; char delimiter = '='; - for (std::string str : readLines) { + for (std::string &str : readLines) { std::stringstream ss(str); std::string key; diff --git a/src/common/virtual_interface.cpp b/src/common/virtual_interface.cpp index 40346aa..f6c9666 100644 --- a/src/common/virtual_interface.cpp +++ b/src/common/virtual_interface.cpp @@ -42,7 +42,7 @@ namespace ColumnLynx::Net { sc.sc_family = AF_SYSTEM; sc.ss_sysaddr = AF_SYS_CONTROL; sc.sc_id = ctlInfo.ctl_id; - sc.sc_unit = 0; // utun0 (0 = auto-assign) + sc.sc_unit = 0; // lynx0 (0 = auto-assign) if (connect(mFd, (struct sockaddr*)&sc, sizeof(sc)) < 0) { if (errno == EPERM) @@ -188,11 +188,12 @@ namespace ColumnLynx::Net { std::string ipStr = ipv4ToString(clientIP); std::string peerStr = ipv4ToString(serverIP); + std::string prefixStr = ipv4ToString(prefixLen); // Set netmask (/24 CIDR temporarily with raw command, improve later) snprintf(cmd, sizeof(cmd), - "ifconfig utun0 %s %s mtu %d netmask 255.255.255.0 up", - ipStr.c_str(), peerStr.c_str(), mtu); + "ifconfig lynx0 %s %s mtu %d netmask %s up", + ipStr.c_str(), peerStr.c_str(), mtu, prefixStr.c_str()); system(cmd); Utils::log("Executed command: " + std::string(cmd)); @@ -203,22 +204,36 @@ namespace ColumnLynx::Net { // ------------------------------------------------------------ // Windows (Wintun) // ------------------------------------------------------------ - bool VirtualInterface::mApplyWindowsIP(uint32_t clientIP, uint32_t serverIP, - uint8_t prefixLen, uint16_t mtu) + bool VirtualInterface::mApplyWindowsIP(uint32_t clientIP, + uint32_t serverIP, + uint8_t prefixLen, + uint16_t mtu) { #ifdef _WIN32 - char ip[32], gw[32]; - strcpy(ip, ipv4ToString(clientIP).c_str()); - strcpy(gw, ipv4ToString(serverIP).c_str()); - + std::string ip = ipv4ToString(clientIP); + std::string gw = ipv4ToString(serverIP); + std::string mask; + + // Convert prefixLen → subnet mask + uint32_t maskInt = (prefixLen == 0) ? 0 : (0xFFFFFFFF << (32 - prefixLen)); + mask = ipv4ToString(maskInt); + char cmd[256]; + + // 1. Set the static IP + mask + gateway snprintf(cmd, sizeof(cmd), - "netsh interface ip set address name=\"%s\" static %s %d.%d.%d.%d", - mIfName.c_str(), ip, - (prefixLen <= 8) ? ((prefixLen << 3) & 255) : 255, - 255, 255, 255); + "netsh interface ip set address name=\"%s\" static %s %s %s", + mIfName.c_str(), ip.c_str(), mask.c_str(), gw.c_str() + ); system(cmd); - + + // 2. Set MTU (separate command) + snprintf(cmd, sizeof(cmd), + "netsh interface ipv4 set subinterface \"%s\" mtu=%u store=persistent", + mIfName.c_str(), mtu + ); + system(cmd); + return true; #else return false; diff --git a/src/server/main.cpp b/src/server/main.cpp index 4cda3de..c40eaa4 100644 --- a/src/server/main.cpp +++ b/src/server/main.cpp @@ -66,7 +66,7 @@ int main(int argc, char** argv) { WintunInitialize(); #endif - std::shared_ptr tun = std::make_shared("utun0"); + std::shared_ptr tun = std::make_shared("lynx0"); log("Using virtual interface: " + tun->getName()); // Generate a temporary keypair, replace with actual CA signed keys later (Note, these are stored in memory) diff --git a/src/server/server/net/tcp/tcp_connection.cpp b/src/server/server/net/tcp/tcp_connection.cpp index cd2433d..a95e2fb 100644 --- a/src/server/server/net/tcp/tcp_connection.cpp +++ b/src/server/server/net/tcp/tcp_connection.cpp @@ -118,7 +118,14 @@ namespace ColumnLynx::Net::TCP { std::memcpy(signPk.data(), data.data() + 1, std::min(data.size() - 1, sizeof(signPk))); // We can safely store this without further checking, the client will need to send the encrypted AES key in a way where they must possess the corresponding private key anyways. - crypto_sign_ed25519_pk_to_curve25519(mConnectionPublicKey.data(), signPk.data()); // Store the client's public encryption key key (for identification) + int r = crypto_sign_ed25519_pk_to_curve25519(mConnectionPublicKey.data(), signPk.data()); // Store the client's public encryption key key (for identification) + if (r != 0) { + Utils::error("Conversion of client signing key to encryption key failed! Killing connection from " + reqAddr); + disconnect(); + + return; + } + Utils::debug("Client " + reqAddr + " converted public encryption key: " + Utils::bytesToHexString(mConnectionPublicKey.data(), 32)); Utils::debug("Key attempted connect: " + Utils::bytesToHexString(signPk.data(), signPk.size())); diff --git a/src/server/server/net/tcp/tcp_server.cpp b/src/server/server/net/tcp/tcp_server.cpp index 3069e3d..98dc691 100644 --- a/src/server/server/net/tcp/tcp_server.cpp +++ b/src/server/server/net/tcp/tcp_server.cpp @@ -2,8 +2,6 @@ // Copyright (C) 2025 DcruBro // Distributed under the terms of the GNU General Public License, either version 2 only or version 3. See LICENSES/ for details. -#pragma once - #include #include @@ -63,7 +61,7 @@ namespace ColumnLynx::Net::TCP { // Snapshot to avoid iterator invalidation while callbacks erase() std::vector> snapshot(mClients.begin(), mClients.end()); - for (auto& client : snapshot) { + for (auto &client : snapshot) { try { client->disconnect(); // should shutdown+close the socket Utils::log("GRACEFUL_DISCONNECT sent to session: " + std::to_string(client->getSessionID()));