Skip to content

Commit

Permalink
v2.10.9
Browse files Browse the repository at this point in the history
  • Loading branch information
bernerdad committed Apr 30, 2024
1 parent a001a6f commit b39def1
Show file tree
Hide file tree
Showing 149 changed files with 1,987 additions and 2,048 deletions.
2 changes: 2 additions & 0 deletions backend/linux/helper/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ project(helper)

find_package(Boost REQUIRED COMPONENTS serialization thread filesystem)
find_package(OpenSSL REQUIRED)
find_package(skyr-url CONFIG REQUIRED)

add_subdirectory(../../../libs/wsnet wsnet)

Expand Down Expand Up @@ -59,6 +60,7 @@ target_link_libraries(helper
Boost::thread
Boost::filesystem
OpenSSL::Crypto
skyr::skyr-url
)

target_include_directories(helper PRIVATE
Expand Down
115 changes: 5 additions & 110 deletions backend/linux/helper/ipc/helper_security.cpp
Original file line number Diff line number Diff line change
@@ -1,130 +1,25 @@
#include <limits.h>
#include <fstream>
#include <grp.h>
#include <sstream>
#include <sys/types.h>

#include "helper_security.h"

#if defined(USE_SIGNATURE_CHECK)
#include "boost/filesystem/path.hpp"

#include "../logger.h"

#include "../../../../client/common/utils/executable_signature/executable_signature.h"

// Expects symLink to reference /path/*/exe, where * can be 'self', or a pid, or
// an exe name.
static std::string getProcessPath(const char* symLink)
{
std::string result;
result.resize(128);

ssize_t rlin_size = ::readlink(symLink, &result[0], result.size() - 1);
while (rlin_size == static_cast<int>(result.size() - 1))
{
// readlink(2) will fill our buffer and not necessarily terminate with NUL;
if (result.size() >= PATH_MAX)
{
errno = ENAMETOOLONG;
result.clear();
return result;
}

result.resize(result.size() * 2);
rlin_size = ::readlink(symLink, &result[0], result.size() - 1);
}

if (rlin_size == -1) {
result.clear();
}
else {
result.resize(rlin_size);
}

return result;
}

// Returns the full path and name of the executable associated with this pid, or an
// empty string if an error occurs.
static std::string getProcessPath(pid_t pid)
{
std::ostringstream stream;
stream << "/proc/" << pid << "/exe";
std::string symLink = stream.str();

return getProcessPath(symLink.c_str());
}

// Returns the directory that contains the application executable.
static std::string applicationDirPath()
{
std::string procPath = getProcessPath("/proc/self/exe");

if (!procPath.empty())
{
boost::filesystem::path path(procPath);
if (path.has_parent_path()) {
return path.parent_path().native();
}
}

return std::string();
}
#endif

void HelperSecurity::reset()
{
pid_validity_cache_.clear();
}

bool HelperSecurity::verifyProcessId(pid_t pid)
{
#if defined(USE_SIGNATURE_CHECK)
const auto it = pid_validity_cache_.find(pid);
if (it != pid_validity_cache_.end())
return it->second;
#endif

return verifyProcessIdImpl(pid);
}

bool HelperSecurity::verifyProcessIdImpl(pid_t pid)
bool HelperSecurity::verifySignature()
{
#if defined(USE_SIGNATURE_CHECK)
//Logger::instance().out("Getting exe path and name for PID %i", pid);

const std::string clientAppPath = getProcessPath(pid);
if (clientAppPath.empty())
{
Logger::instance().out("Failed to get exe path and name for PID %i, errno %d", pid, errno);
pid_validity_cache_[pid] = false;
return false;
}

const std::string engineExePath = applicationDirPath() + "/Windscribe";

//Logger::instance().out("Checking exe path matches engine's: %s", clientAppPath.c_str());

if (engineExePath.compare(clientAppPath) != 0)
{
Logger::instance().out("Invalid calling application for PID %i, %s", pid, clientAppPath.c_str());
pid_validity_cache_[pid] = false;
return false;
}

//Logger::instance().out("Verifying signature...");

ExecutableSignature sigCheck;
bool result = sigCheck.verify(engineExePath);
bool result = sigCheck.verify("/opt/windscribe/Windscribe");

if (!result) {
Logger::instance().out("Signature verification failed for PID %i, %s", pid, sigCheck.lastError().c_str());
Logger::instance().out("Signature verification failed for Windscribe: %s", sigCheck.lastError().c_str());
}

pid_validity_cache_[pid] = result;

return result;
#else
(void)pid;
return true;
#endif
}
11 changes: 2 additions & 9 deletions backend/linux/helper/ipc/helper_security.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,6 @@ class HelperSecurity
return single_instance;
}

// Reset cached validity.
void reset();

// Check if process id is a trusted Windscribe engine app.
bool verifyProcessId(pid_t pid);

private:
bool verifyProcessIdImpl(pid_t pid);
std::map<pid_t,bool> pid_validity_cache_;
// Check if process has the correct signature.
bool verifySignature();
};
31 changes: 27 additions & 4 deletions backend/linux/helper/ovpn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@
namespace OVPN
{

bool writeOVPNFile(const std::string &dnsScript, const std::string &config, bool isCustomConfig)
bool writeOVPNFile(const std::string &dnsScript, int port, const std::string &config, const std::string &httpProxy, int httpPort, const std::string &socksProxy, int socksPort, bool isCustomConfig)
{
std::istringstream stream(config);
std::string line;
int bytes;

int fd = open("/etc/windscribe/config.ovpn", O_CREAT | O_WRONLY | O_TRUNC, S_IRWXU | S_IRGRP | S_IROTH);
if (fd < 0) {
Logger::instance().out("Could not open firewall rules for writing");
Logger::instance().out("Could not open config for writing");
return false;
}

Expand All @@ -25,7 +25,7 @@ bool writeOVPNFile(const std::string &dnsScript, const std::string &config, bool
line.erase(0, line.find_first_not_of(" \n\r\t"));
line.erase(line.find_last_not_of(" \n\r\t") + 1);

// filter anything that runs an external script
// filter anything that runs an external script, or we need to override
// check for up to offset of 2 in case the command starts with '--'
if (line.rfind("up", 2) != std::string::npos ||
line.rfind("tls-verify", 2) != std::string::npos ||
Expand All @@ -36,7 +36,10 @@ bool writeOVPNFile(const std::string &dnsScript, const std::string &config, bool
line.rfind("client-disconnect", 2) != std::string::npos ||
line.rfind("down", 2) != std::string::npos ||
line.rfind("learn-address", 2) != std::string::npos ||
line.rfind("auth-user-pass-verify", 2) != std::string::npos)
line.rfind("auth-user-pass-verify", 2) != std::string::npos ||
line.rfind("management", 2) != std::string::npos ||
line.rfind("http-proxy", 2) != std::string::npos ||
line.rfind("socks-proxy", 2) != std::string::npos)
{
continue;
}
Expand Down Expand Up @@ -65,6 +68,26 @@ bool writeOVPNFile(const std::string &dnsScript, const std::string &config, bool
return false;
}
}

// add management and other options
std::string opts = \
"management 127.0.0.1 " + std::to_string(port) + "\n" \
"management-query-passwords\n" \
"management-hold\n";

if (httpProxy.length() > 0) {
opts += "http-proxy " + httpProxy + " " + std::to_string(httpPort) + " auto\n";
} else if (socksProxy.length() > 0) {
opts += "socks-proxy " + socksProxy + " " + std::to_string(socksPort) + "\n";
}

bytes = write(fd, opts.c_str(), opts.length());
if (bytes <= 0) {
Logger::instance().out("Could not write additional options");
close(fd);
return false;
}

close(fd);
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion backend/linux/helper/ovpn.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@

namespace OVPN {

bool writeOVPNFile(const std::string &dnsScript, const std::string &config, bool isCustomConfig);
bool writeOVPNFile(const std::string &dnsScript, int port, const std::string &config, const std::string &httpProxy, int httpPort, const std::string &socksProxy, int socksPort, bool isCustomConfig);

} // namespace OVPN

0 comments on commit b39def1

Please sign in to comment.