diff --git a/.gitmodules b/.gitmodules index ad9a3025..9a58a7e9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "ext/gmock"] path = ext/gmock url = https://github.com/google/googlemock.git +[submodule "ext/gulrak-filesystem"] + path = ext/gulrak-filesystem + url = https://github.com/gulrak/filesystem diff --git a/CMakeLists.txt b/CMakeLists.txt index 1588ad7a..8653a2c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -301,6 +301,8 @@ elseif (${CMAKE_SYSTEM_NAME} MATCHES "Windows") ) endif() +include_directories("${CMAKE_SOURCE_DIR}/ext/gulrak-filesystem/include") + # # OpenSSL # diff --git a/ext/gulrak-filesystem b/ext/gulrak-filesystem new file mode 160000 index 00000000..614bbe87 --- /dev/null +++ b/ext/gulrak-filesystem @@ -0,0 +1 @@ +Subproject commit 614bbe87b80435d87ab8791564370e0c1d13627d diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index ccb5c196..87f31eb2 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -442,7 +442,7 @@ void MainWindow::checkFingerprint(const QString& line) barrier::string::from_hex(fingerprintRegex.cap(2).toStdString()) }; - auto db_path = DataDirectories::trusted_servers_ssl_fingerprints_path(); + auto db_path = barrier::DataDirectories::trusted_servers_ssl_fingerprints_path(); // We compare only SHA256 fingerprints, but show both SHA1 and SHA256 so that the users can // still verify fingerprints on old Barrier servers. This way the only time when we are exposed @@ -564,7 +564,7 @@ void MainWindow::startBarrier() // launched the process (e.g. when launched with elevation). setting the // profile dir on launch ensures it uses the same profile dir is used // no matter how its relaunched. - args << "--profile-dir" << QString::fromStdString("\"" + DataDirectories::profile() + "\""); + args << "--profile-dir" << QString::fromStdString("\"" + barrier::DataDirectories::profile().u8string() + "\""); #endif if ((barrierType() == barrierClient && !clientArgs(args, app)) @@ -1020,8 +1020,8 @@ void MainWindow::updateSSLFingerprint() return; } - auto local_path = DataDirectories::local_ssl_fingerprints_path(); - if (!QFile::exists(QString::fromStdString(local_path))) { + auto local_path = barrier::DataDirectories::local_ssl_fingerprints_path(); + if (!barrier::fs::exists(local_path)) { return; } diff --git a/src/gui/src/SslCertificate.cpp b/src/gui/src/SslCertificate.cpp index ea770503..26f3b3ee 100644 --- a/src/gui/src/SslCertificate.cpp +++ b/src/gui/src/SslCertificate.cpp @@ -18,45 +18,36 @@ #include "SslCertificate.h" #include "common/DataDirectories.h" #include "base/finally.h" -#include "io/fstream.h" +#include "io/filesystem.h" #include "net/FingerprintDatabase.h" #include "net/SecureUtils.h" -#include -#include -#include - #include #include #include #include #include -static const char kCertificateFilename[] = "Barrier.pem"; -static const char kSslDir[] = "SSL"; - SslCertificate::SslCertificate(QObject *parent) : QObject(parent) { - m_ProfileDir = DataDirectories::profile(); - if (m_ProfileDir.empty()) { + if (barrier::DataDirectories::profile().empty()) { emit error(tr("Failed to get profile directory.")); } } void SslCertificate::generateCertificate() { - auto cert_path = getCertificatePath(); - - QFile file(QString::fromStdString(cert_path)); - if (!file.exists() || !isCertificateValid(cert_path)) { - QDir sslDir(QString::fromStdString(getCertificateDirectory())); - if (!sslDir.exists()) { - sslDir.mkpath("."); - } + auto cert_path = barrier::DataDirectories::ssl_certificate_path(); + if (!barrier::fs::exists(cert_path) || !is_certificate_valid(cert_path)) { try { - barrier::generate_pem_self_signed_cert(cert_path); + auto cert_dir = cert_path.parent_path(); + if (!barrier::fs::exists(cert_dir)) { + barrier::fs::create_directories(cert_dir); + } + + barrier::generate_pem_self_signed_cert(cert_path.u8string()); } catch (const std::exception& e) { emit error(QString("SSL tool failed: %1").arg(e.what())); return; @@ -65,19 +56,19 @@ void SslCertificate::generateCertificate() emit info(tr("SSL certificate generated.")); } - generateFingerprint(cert_path); + generate_fingerprint(cert_path); emit generateFinished(); } -void SslCertificate::generateFingerprint(const std::string& cert_path) +void SslCertificate::generate_fingerprint(const barrier::fs::path& cert_path) { try { - auto local_path = DataDirectories::local_ssl_fingerprints_path(); + auto local_path = barrier::DataDirectories::local_ssl_fingerprints_path(); barrier::FingerprintDatabase db; - db.add_trusted(barrier::get_pem_file_cert_fingerprint(cert_path, + db.add_trusted(barrier::get_pem_file_cert_fingerprint(cert_path.u8string(), barrier::FingerprintType::SHA1)); - db.add_trusted(barrier::get_pem_file_cert_fingerprint(cert_path, + db.add_trusted(barrier::get_pem_file_cert_fingerprint(cert_path.u8string(), barrier::FingerprintType::SHA256)); db.write(local_path); @@ -87,17 +78,7 @@ void SslCertificate::generateFingerprint(const std::string& cert_path) } } -std::string SslCertificate::getCertificatePath() -{ - return getCertificateDirectory() + QDir::separator().toLatin1() + kCertificateFilename; -} - -std::string SslCertificate::getCertificateDirectory() -{ - return m_ProfileDir + QDir::separator().toLatin1() + kSslDir; -} - -bool SslCertificate::isCertificateValid(const std::string& path) +bool SslCertificate::is_certificate_valid(const barrier::fs::path& path) { OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); diff --git a/src/gui/src/SslCertificate.h b/src/gui/src/SslCertificate.h index 7f77771a..eae7fd6c 100644 --- a/src/gui/src/SslCertificate.h +++ b/src/gui/src/SslCertificate.h @@ -19,6 +19,7 @@ #include #include +#include "io/filesystem.h" class SslCertificate : public QObject { @@ -36,13 +37,7 @@ signals: void generateFinished(); private: - std::pair runTool(const QStringList& args); - void generateFingerprint(const std::string& cert_path); + void generate_fingerprint(const barrier::fs::path& cert_path); - std::string getCertificatePath(); - std::string getCertificateDirectory(); - - bool isCertificateValid(const std::string& path); -private: - std::string m_ProfileDir; + bool is_certificate_valid(const barrier::fs::path& path); }; diff --git a/src/lib/barrier/App.cpp b/src/lib/barrier/App.cpp index f0aea6a5..67e58aba 100644 --- a/src/lib/barrier/App.cpp +++ b/src/lib/barrier/App.cpp @@ -164,7 +164,7 @@ App::initApp(int argc, const char** argv) // parse command line parseArgs(argc, argv); - DataDirectories::profile(argsBase().m_profileDirectory); + barrier::DataDirectories::profile(argsBase().m_profileDirectory); // set log filter if (!CLOG->setFilter(argsBase().m_logFilter)) { diff --git a/src/lib/barrier/ArgParser.cpp b/src/lib/barrier/ArgParser.cpp index 4c57e798..44e29491 100644 --- a/src/lib/barrier/ArgParser.cpp +++ b/src/lib/barrier/ArgParser.cpp @@ -24,7 +24,7 @@ #include "barrier/ArgsBase.h" #include "base/Log.h" #include "base/String.h" -#include "common/PathUtilities.h" +#include "io/filesystem.h" #ifdef WINAPI_MSWINDOWS #include @@ -288,10 +288,10 @@ ArgParser::parseGenericArgs(int argc, const char* const* argv, int& i) argsBase().m_enableCrypto = false; } else if (isArg(i, argc, argv, NULL, "--profile-dir", 1)) { - argsBase().m_profileDirectory = argv[++i]; + argsBase().m_profileDirectory = barrier::fs::u8path(argv[++i]); } else if (isArg(i, argc, argv, NULL, "--plugin-dir", 1)) { - argsBase().m_pluginDirectory = argv[++i]; + argsBase().m_pluginDirectory = barrier::fs::u8path(argv[++i]); } else { // option not supported here @@ -487,7 +487,13 @@ void ArgParser::updateCommonArgs(const char* const* argv) { argsBase().m_name = ARCH->getHostName(); - argsBase().m_exename = PathUtilities::basename(argv[0]); + argsBase().m_exename = parse_exename(argv[0]); +} + +std::string ArgParser::parse_exename(const char* arg) +{ + // FIXME: we assume UTF-8 encoding, but on Windows this is not correct + return barrier::fs::u8path(arg).filename().u8string(); } bool diff --git a/src/lib/barrier/ArgParser.h b/src/lib/barrier/ArgParser.h index c8e9e68d..472d93a1 100644 --- a/src/lib/barrier/ArgParser.h +++ b/src/lib/barrier/ArgParser.h @@ -48,11 +48,14 @@ public: static String assembleCommand(std::vector& argsArray, String ignoreArg = "", int parametersRequired = 0); + static std::string parse_exename(const char* arg); + private: void updateCommonArgs(const char* const* argv); bool checkUnexpectedArgs(); static ArgsBase& argsBase() { return *m_argsBase; } + bool parseMSWindowsArg(ArgsBase& argsBase, const int& argc, const char* const* argv, int& i); bool parseCarbonArg(ArgsBase& argsBase, const int& argc, const char* const* argv, int& i); bool parseXWindowsArg(ArgsBase& argsBase, const int& argc, const char* const* argv, int& i); diff --git a/src/lib/barrier/ArgsBase.cpp b/src/lib/barrier/ArgsBase.cpp index b392339a..e3e38031 100644 --- a/src/lib/barrier/ArgsBase.cpp +++ b/src/lib/barrier/ArgsBase.cpp @@ -43,7 +43,7 @@ m_dropTarget(""), m_shouldExit(false), m_barrierAddress(), m_enableCrypto(true), -m_profileDirectory(""), +m_profileDirectory(), m_pluginDirectory("") { } diff --git a/src/lib/barrier/ArgsBase.h b/src/lib/barrier/ArgsBase.h index ad442dc9..cdb50928 100644 --- a/src/lib/barrier/ArgsBase.h +++ b/src/lib/barrier/ArgsBase.h @@ -19,6 +19,7 @@ #pragma once #include "base/String.h" +#include "io/filesystem.h" class ArgsBase { public: @@ -50,6 +51,6 @@ public: bool m_shouldExit; String m_barrierAddress; bool m_enableCrypto; - String m_profileDirectory; - String m_pluginDirectory; + barrier::fs::path m_profileDirectory; + barrier::fs::path m_pluginDirectory; }; diff --git a/src/lib/barrier/ClientApp.cpp b/src/lib/barrier/ClientApp.cpp index ec687e1e..a466f30e 100644 --- a/src/lib/barrier/ClientApp.cpp +++ b/src/lib/barrier/ClientApp.cpp @@ -40,7 +40,6 @@ #include "base/TMethodJob.h" #include "base/Log.h" #include "common/Version.h" -#include "common/PathUtilities.h" #if WINAPI_MSWINDOWS #include "platform/MSWindowsScreen.h" @@ -522,7 +521,7 @@ ClientApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc { // general initialization m_serverAddress = new NetworkAddress; - args().m_exename = PathUtilities::basename(argv[0]); + argsBase().m_exename = ArgParser::parse_exename(argv[0]); // install caller's output filter if (outputter != NULL) { diff --git a/src/lib/barrier/DropHelper.cpp b/src/lib/barrier/DropHelper.cpp index 32f20cfc..af22b523 100644 --- a/src/lib/barrier/DropHelper.cpp +++ b/src/lib/barrier/DropHelper.cpp @@ -18,7 +18,7 @@ #include "barrier/DropHelper.h" #include "base/Log.h" -#include "io/fstream.h" +#include "io/filesystem.h" #include diff --git a/src/lib/barrier/ServerApp.cpp b/src/lib/barrier/ServerApp.cpp index 599bde70..bbb35dd5 100644 --- a/src/lib/barrier/ServerApp.cpp +++ b/src/lib/barrier/ServerApp.cpp @@ -40,7 +40,6 @@ #include "base/TMethodEventJob.h" #include "common/Version.h" #include "common/DataDirectories.h" -#include "common/PathUtilities.h" #if SYSAPI_WIN32 #include "arch/win32/ArchMiscWindows.h" @@ -129,11 +128,15 @@ ServerApp::help() #endif // refer to custom profile directory even if not saved yet - String profilePath = argsBase().m_profileDirectory; - if (profilePath.empty()) { - profilePath = DataDirectories::profile(); + barrier::fs::path profile_path = argsBase().m_profileDirectory; + if (profile_path.empty()) { + profile_path = barrier::DataDirectories::profile(); } + auto usr_config_path = (profile_path / barrier::fs::u8path(USR_CONFIG_NAME)).u8string(); + auto sys_config_path = (barrier::DataDirectories::systemconfig() / + barrier::fs::u8path(SYS_CONFIG_NAME)).u8string(); + std::ostringstream buffer; buffer << "Start the barrier server component.\n" << "\n" @@ -156,8 +159,8 @@ ServerApp::help() << "\n" << "If no configuration file pathname is provided then the first of the\n" << "following to load successfully sets the configuration:\n" - << " " << PathUtilities::concat(profilePath, USR_CONFIG_NAME) << "\n" - << " " << PathUtilities::concat(DataDirectories::systemconfig(), SYS_CONFIG_NAME) << "\n"; + << " " << usr_config_path << "\n" + << " " << sys_config_path << "\n"; LOG((CLOG_PRINT "%s", buffer.str().c_str())); } @@ -194,25 +197,25 @@ ServerApp::loadConfig() // load the default configuration if no explicit file given else { - String path = DataDirectories::profile(); + auto path = barrier::DataDirectories::profile(); if (!path.empty()) { // complete path - path = PathUtilities::concat(path, USR_CONFIG_NAME); + path /= barrier::fs::u8path(USR_CONFIG_NAME); // now try loading the user's configuration - if (loadConfig(path)) { + if (loadConfig(path.u8string())) { loaded = true; - args().m_configFile = path; + args().m_configFile = path.u8string(); } } if (!loaded) { // try the system-wide config file - path = DataDirectories::systemconfig(); + path = barrier::DataDirectories::systemconfig(); if (!path.empty()) { - path = PathUtilities::concat(path, SYS_CONFIG_NAME); - if (loadConfig(path)) { + path /= barrier::fs::u8path(SYS_CONFIG_NAME); + if (loadConfig(path.u8string())) { loaded = true; - args().m_configFile = path; + args().m_configFile = path.u8string(); } } } @@ -832,7 +835,7 @@ ServerApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc // general initialization m_barrierAddress = new NetworkAddress; args().m_config = new Config(m_events); - args().m_exename = PathUtilities::basename(argv[0]); + args().m_exename = ArgParser::parse_exename(argv[0]); // install caller's output filter if (outputter != NULL) { diff --git a/src/lib/barrier/win32/DaemonApp.cpp b/src/lib/barrier/win32/DaemonApp.cpp index 88e6b4ef..6ea6a4fa 100644 --- a/src/lib/barrier/win32/DaemonApp.cpp +++ b/src/lib/barrier/win32/DaemonApp.cpp @@ -245,7 +245,7 @@ DaemonApp::logFilename() { string logFilename = ARCH->setting("LogFilename"); if (logFilename.empty()) - logFilename = DataDirectories::global() + "\\" + LOG_FILENAME; + logFilename = (barrier::DataDirectories::global() / LOG_FILENAME).u8string(); MSWindowsUtil::createDirectory(logFilename, true); return logFilename; } diff --git a/src/lib/base/log_outputters.cpp b/src/lib/base/log_outputters.cpp index 6d3374b5..a1193c78 100644 --- a/src/lib/base/log_outputters.cpp +++ b/src/lib/base/log_outputters.cpp @@ -20,7 +20,7 @@ #include "base/TMethodJob.h" #include "arch/Arch.h" #include "base/String.h" -#include "io/fstream.h" +#include "io/filesystem.h" #include enum EFileLogOutputter { diff --git a/src/lib/common/DataDirectories.h b/src/lib/common/DataDirectories.h index 4489ac24..45502116 100644 --- a/src/lib/common/DataDirectories.h +++ b/src/lib/common/DataDirectories.h @@ -15,28 +15,36 @@ * along with this program. If not, see . */ -#pragma once +#ifndef BARRIER_LIB_COMMON_DATA_DIRECTORIES_H +#define BARRIER_LIB_COMMON_DATA_DIRECTORIES_H -#include +#include "io/filesystem.h" + +namespace barrier { class DataDirectories { public: - static const std::string& profile(); - static const std::string& profile(const std::string& path); + static const fs::path& profile(); + static const fs::path& profile(const fs::path& path); - static const std::string& global(); - static const std::string& global(const std::string& path); + static const fs::path& global(); + static const fs::path& global(const fs::path& path); - static const std::string& systemconfig(); - static const std::string& systemconfig(const std::string& path); + static const fs::path& systemconfig(); + static const fs::path& systemconfig(const fs::path& path); - static std::string ssl_fingerprints_path(); - static std::string local_ssl_fingerprints_path(); - static std::string trusted_servers_ssl_fingerprints_path(); - static std::string trusted_clients_ssl_fingerprints_path(); + static fs::path ssl_fingerprints_path(); + static fs::path local_ssl_fingerprints_path(); + static fs::path trusted_servers_ssl_fingerprints_path(); + static fs::path trusted_clients_ssl_fingerprints_path(); + static fs::path ssl_certificate_path(); private: - static std::string _profile; - static std::string _global; - static std::string _systemconfig; + static fs::path _profile; + static fs::path _global; + static fs::path _systemconfig; }; + +} // namespace barrier + +#endif diff --git a/src/lib/common/DataDirectories_static.cpp b/src/lib/common/DataDirectories_static.cpp index 5e28e055..47f88e70 100644 --- a/src/lib/common/DataDirectories_static.cpp +++ b/src/lib/common/DataDirectories_static.cpp @@ -17,32 +17,40 @@ #include "DataDirectories.h" -// static member -std::string DataDirectories::_profile; -std::string DataDirectories::_global; -std::string DataDirectories::_systemconfig; +namespace barrier { + +fs::path DataDirectories::_profile; +fs::path DataDirectories::_global; +fs::path DataDirectories::_systemconfig; static const char kFingerprintsDirName[] = "SSL/Fingerprints"; static const char kFingerprintsLocalFilename[] = "Local.txt"; static const char kFingerprintsTrustedServersFilename[] = "TrustedServers.txt"; static const char kFingerprintsTrustedClientsFilename[] = "TrustedClients.txt"; -std::string DataDirectories::ssl_fingerprints_path() +fs::path DataDirectories::ssl_fingerprints_path() { - return profile() + "/" + kFingerprintsDirName; + return profile() / kFingerprintsDirName; } -std::string DataDirectories::local_ssl_fingerprints_path() +fs::path DataDirectories::local_ssl_fingerprints_path() { - return ssl_fingerprints_path() + "/" + kFingerprintsLocalFilename; + return ssl_fingerprints_path() / kFingerprintsLocalFilename; } -std::string DataDirectories::trusted_servers_ssl_fingerprints_path() +fs::path DataDirectories::trusted_servers_ssl_fingerprints_path() { - return ssl_fingerprints_path() + "/" + kFingerprintsTrustedServersFilename; + return ssl_fingerprints_path() / kFingerprintsTrustedServersFilename; } -std::string DataDirectories::trusted_clients_ssl_fingerprints_path() +fs::path DataDirectories::trusted_clients_ssl_fingerprints_path() { - return ssl_fingerprints_path() + "/" + kFingerprintsTrustedClientsFilename; + return ssl_fingerprints_path() / kFingerprintsTrustedClientsFilename; } + +fs::path DataDirectories::ssl_certificate_path() +{ + return profile() / "SSL" / "Barrier.pem"; +} + +} // namespace barrier diff --git a/src/lib/common/MacOSXPrecomp.h b/src/lib/common/MacOSXPrecomp.h deleted file mode 100644 index 53ecc83c..00000000 --- a/src/lib/common/MacOSXPrecomp.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * barrier -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file LICENSE that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - // -// Prefix header for all source files of the 'deleteme' target in the 'deleteme' project. -// - -#include diff --git a/src/lib/common/PathUtilities.cpp b/src/lib/common/PathUtilities.cpp deleted file mode 100644 index a2ab38a2..00000000 --- a/src/lib/common/PathUtilities.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* -* barrier -- mouse and keyboard sharing utility -* Copyright (C) 2018 Debauchee Open Source Group -* -* This package is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* found in the file LICENSE that should have accompanied this file. -* -* This package is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -/* - -These functions cover the vast majority of cases for different paths across -windows and unixes. They are not, however, fullproof and probably don't cover -fringe cases very well. The library below might be used as an alternative if -these implementations prove to be insufficient. As the library's readme states -it is simply a temporary band-aid until std::filesystem is integrated (C++17 -has it in std::experimental) and this class should also be treated as such. - -https://github.com/wjakob/filesystem/ - -*/ - -#include "PathUtilities.h" - -// keep the default platform delimiter as the first in the list -#ifdef _WIN32 -static const char *Delimiters = "\\/"; -#else -static const char *Delimiters = "/"; -#endif - -static const char DefaultDelimiter = Delimiters[0]; - -std::string PathUtilities::basename(const std::string& path) -{ - return path.substr(path.find_last_of(Delimiters) + 1); -} - -std::string PathUtilities::concat(const std::string& left, const std::string& right) -{ - // although npos is usually (-1) we can't count on that so handle it explicitly - auto leftEnd = left.find_last_not_of(Delimiters); - if (leftEnd == std::string::npos) - leftEnd = 0; - else - ++leftEnd; - auto rightStart = right.find_first_not_of(Delimiters, 0); - if (rightStart == std::string::npos) { - // both left/right are empty - if (left.size() == 0 && right.size() == 0) - return ""; - // right is full of delims, left is okay - if (leftEnd > 0) - return left.substr(0, leftEnd); - // both left/right useless but at least one has delims - return std::string(1, DefaultDelimiter); - } - if (leftEnd == 0) { - // right is okay and not prefixed with delims, left is empty - if (left.size() == 0 && rightStart == 0) - return right.substr(rightStart); - // (right is okay and prefixed with delims) OR left is full of delims - return DefaultDelimiter + right.substr(rightStart); - } - // concatenation using both left and right - return left.substr(0, leftEnd) + DefaultDelimiter + right.substr(rightStart); -} diff --git a/src/lib/common/PathUtilities.h b/src/lib/common/PathUtilities.h deleted file mode 100644 index 30313243..00000000 --- a/src/lib/common/PathUtilities.h +++ /dev/null @@ -1,27 +0,0 @@ -/* -* barrier -- mouse and keyboard sharing utility -* Copyright (C) 2018 Debauchee Open Source Group -* -* This package is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* found in the file LICENSE that should have accompanied this file. -* -* This package is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#pragma once - -#include - -class PathUtilities -{ -public: - static std::string basename(const std::string& path); - static std::string concat(const std::string& left, const std::string& right); -}; diff --git a/src/lib/common/unix/DataDirectories.cpp b/src/lib/common/unix/DataDirectories.cpp index 608db05c..cf3ca243 100644 --- a/src/lib/common/unix/DataDirectories.cpp +++ b/src/lib/common/unix/DataDirectories.cpp @@ -22,7 +22,7 @@ #include // getpwuid(_r) #include // getpwuid(_r) -const std::string ProfileSubdir = "/barrier"; +namespace barrier { static std::string pw_dir(struct passwd* pwentp) { @@ -33,7 +33,7 @@ static std::string pw_dir(struct passwd* pwentp) #ifdef HAVE_GETPWUID_R -static std::string unix_home() +static fs::path unix_home() { long size = -1; #if defined(_SC_GETPW_R_SIZE_MAX) @@ -46,47 +46,47 @@ static std::string unix_home() struct passwd* pwentp; std::string buffer(size, 0); getpwuid_r(getuid(), &pwent, &buffer[0], size, &pwentp); - return pw_dir(pwentp); + return fs::u8path(pw_dir(pwentp)); } #else // not HAVE_GETPWUID_R -static std::string unix_home() +static fs::path unix_home() { - return pw_dir(getpwuid(getuid())); + return fs::u8path(pw_dir(getpwuid(getuid()))); } #endif // HAVE_GETPWUID_R -static std::string profile_basedir() +static fs::path profile_basedir() { #ifdef WINAPI_XWINDOWS // linux/bsd adheres to freedesktop standards // https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html const char* dir = std::getenv("XDG_DATA_HOME"); if (dir != NULL) - return dir; - return unix_home() + "/.local/share"; + return fs::u8path(dir); + return unix_home() / ".local/share"; #else // macos has its own standards // https://developer.apple.com/library/content/documentation/General/Conceptual/MOSXAppProgrammingGuide/AppRuntime/AppRuntime.html - return unix_home() + "/Library/Application Support"; + return unix_home() / "Library/Application Support"; #endif } -const std::string& DataDirectories::profile() +const fs::path& DataDirectories::profile() { if (_profile.empty()) - _profile = profile_basedir() + ProfileSubdir; + _profile = profile_basedir() / "barrier"; return _profile; } -const std::string& DataDirectories::profile(const std::string& path) +const fs::path& DataDirectories::profile(const fs::path& path) { _profile = path; return _profile; } -const std::string& DataDirectories::global() +const fs::path& DataDirectories::global() { if (_global.empty()) // TODO: where on a unix system should public/global shared data go? @@ -94,21 +94,23 @@ const std::string& DataDirectories::global() _global = "/tmp"; return _global; } -const std::string& DataDirectories::global(const std::string& path) +const fs::path& DataDirectories::global(const fs::path& path) { _global = path; return _global; } -const std::string& DataDirectories::systemconfig() +const fs::path& DataDirectories::systemconfig() { if (_systemconfig.empty()) _systemconfig = "/etc"; return _systemconfig; } -const std::string& DataDirectories::systemconfig(const std::string& path) +const fs::path& DataDirectories::systemconfig(const fs::path& path) { _systemconfig = path; return _systemconfig; } + +} // namespace barrier diff --git a/src/lib/common/win32/DataDirectories.cpp b/src/lib/common/win32/DataDirectories.cpp index 32bc2136..31a428fd 100644 --- a/src/lib/common/win32/DataDirectories.cpp +++ b/src/lib/common/win32/DataDirectories.cpp @@ -20,43 +20,45 @@ #include -std::string known_folder_path(const KNOWNFOLDERID& id) +namespace barrier { + +fs::path known_folder_path(const KNOWNFOLDERID& id) { - std::string path; + fs::path path; WCHAR* buffer; HRESULT result = SHGetKnownFolderPath(id, 0, NULL, &buffer); if (result == S_OK) { - path = win_wchar_to_utf8(buffer); + path = fs::path(std::wstring(buffer)); CoTaskMemFree(buffer); } return path; } -const std::string& DataDirectories::profile() +const fs::path& DataDirectories::profile() { if (_profile.empty()) - _profile = known_folder_path(FOLDERID_LocalAppData) + "\\Barrier"; + _profile = known_folder_path(FOLDERID_LocalAppData) / "Barrier"; return _profile; } -const std::string& DataDirectories::profile(const std::string& path) +const fs::path& DataDirectories::profile(const fs::path& path) { _profile = path; return _profile; } -const std::string& DataDirectories::global() +const fs::path& DataDirectories::global() { if (_global.empty()) - _global = known_folder_path(FOLDERID_ProgramData) + "\\Barrier"; + _global = known_folder_path(FOLDERID_ProgramData) / "Barrier"; return _global; } -const std::string& DataDirectories::global(const std::string& path) +const fs::path& DataDirectories::global(const fs::path& path) { _global = path; return _global; } -const std::string& DataDirectories::systemconfig() +const fs::path& DataDirectories::systemconfig() { // systemconfig() is a special case in that it will track the current value // of global() unless and until it is explicitly set otherwise @@ -66,8 +68,10 @@ const std::string& DataDirectories::systemconfig() return _systemconfig; } -const std::string& DataDirectories::systemconfig(const std::string& path) +const fs::path& DataDirectories::systemconfig(const fs::path& path) { _systemconfig = path; return _systemconfig; } + +} // namespace barrier diff --git a/src/lib/io/fstream.cpp b/src/lib/io/filesystem.cpp similarity index 57% rename from src/lib/io/fstream.cpp rename to src/lib/io/filesystem.cpp index ea91859d..46ae06db 100644 --- a/src/lib/io/fstream.cpp +++ b/src/lib/io/filesystem.cpp @@ -15,7 +15,10 @@ along with this program. If not, see . */ -#include "fstream.h" +// this header must come first so that it picks up the filesystem implementation +#include + +#include "filesystem.h" #if SYSAPI_WIN32 #include "common/win32/encoding_utilities.h" #endif @@ -26,43 +29,42 @@ namespace barrier { namespace { template -void open_utf8_path_impl(Stream& stream, const std::string& path, std::ios_base::openmode mode) +void open_utf8_path_impl(Stream& stream, const fs::path& path, std::ios_base::openmode mode) { #if SYSAPI_WIN32 - // on Windows we need to use a private constructor from wchar_t* string. - auto wchar_path = utf8_to_win_char(path); - stream.open(wchar_path.data(), mode); + // on Windows we need to use a non-standard constructor from wchar_t* string + // which fs::path::native() returns + stream.open(path.native().c_str(), mode); #else - stream.open(path.c_str(), mode); + stream.open(path.native().c_str(), mode); #endif } } // namespace -void open_utf8_path(std::ifstream& stream, const std::string& path, std::ios_base::openmode mode) +void open_utf8_path(std::ifstream& stream, const fs::path& path, std::ios_base::openmode mode) { open_utf8_path_impl(stream, path, mode); } -void open_utf8_path(std::ofstream& stream, const std::string& path, std::ios_base::openmode mode) +void open_utf8_path(std::ofstream& stream, const fs::path& path, std::ios_base::openmode mode) { open_utf8_path_impl(stream, path, mode); } -void open_utf8_path(std::fstream& stream, const std::string& path, std::ios_base::openmode mode) +void open_utf8_path(std::fstream& stream, const fs::path& path, std::ios_base::openmode mode) { open_utf8_path_impl(stream, path, mode); } -std::FILE* fopen_utf8_path(const std::string& path, const std::string& mode) +std::FILE* fopen_utf8_path(const fs::path& path, const std::string& mode) { #if SYSAPI_WIN32 - auto wchar_path = utf8_to_win_char(path); auto wchar_mode = utf8_to_win_char(mode); - return _wfopen(reinterpret_cast(wchar_path.data()), + return _wfopen(path.native().c_str(), reinterpret_cast(wchar_mode.data())); #else - return std::fopen(path.c_str(), mode.c_str()); + return std::fopen(path.native().c_str(), mode.c_str()); #endif } diff --git a/src/lib/io/fstream.h b/src/lib/io/filesystem.h similarity index 70% rename from src/lib/io/fstream.h rename to src/lib/io/filesystem.h index 2b327f18..78e34230 100644 --- a/src/lib/io/fstream.h +++ b/src/lib/io/filesystem.h @@ -15,24 +15,27 @@ along with this program. If not, see . */ -#ifndef BARRIER_LIB_IO_FSTREAM_H -#define BARRIER_LIB_IO_FSTREAM_H +#ifndef BARRIER_LIB_IO_FILESYSTEM_H +#define BARRIER_LIB_IO_FILESYSTEM_H #include #include #include +#include namespace barrier { -void open_utf8_path(std::ifstream& stream, const std::string& path, +namespace fs = ghc::filesystem; + +void open_utf8_path(std::ifstream& stream, const fs::path& path, std::ios_base::openmode mode = std::ios_base::in); -void open_utf8_path(std::ofstream& stream, const std::string& path, +void open_utf8_path(std::ofstream& stream, const fs::path& path, std::ios_base::openmode mode = std::ios_base::out); -void open_utf8_path(std::fstream& stream, const std::string& path, +void open_utf8_path(std::fstream& stream, const fs::path& path, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out); -std::FILE* fopen_utf8_path(const std::string& path, const std::string& mode); +std::FILE* fopen_utf8_path(const fs::path& path, const std::string& mode); } // namespace barrier -#endif +#endif // BARRIER_LIB_IO_FILESYSTEM_H diff --git a/src/lib/net/FingerprintData.cpp b/src/lib/net/FingerprintData.cpp index f7acbd28..460b39bd 100644 --- a/src/lib/net/FingerprintData.cpp +++ b/src/lib/net/FingerprintData.cpp @@ -17,7 +17,7 @@ #include "base/String.h" #include "FingerprintDatabase.h" -#include "io/fstream.h" +#include "io/filesystem.h" #include #include diff --git a/src/lib/net/FingerprintDatabase.cpp b/src/lib/net/FingerprintDatabase.cpp index 3dcbaee6..def0de91 100644 --- a/src/lib/net/FingerprintDatabase.cpp +++ b/src/lib/net/FingerprintDatabase.cpp @@ -17,20 +17,20 @@ #include "base/String.h" #include "FingerprintDatabase.h" -#include "io/fstream.h" +#include "io/filesystem.h" #include #include namespace barrier { -void FingerprintDatabase::read(const std::string& path) +void FingerprintDatabase::read(const fs::path& path) { std::ifstream file; open_utf8_path(file, path, std::ios_base::in); read_stream(file); } -void FingerprintDatabase::write(const std::string& path) +void FingerprintDatabase::write(const fs::path& path) { std::ofstream file; open_utf8_path(file, path, std::ios_base::out); diff --git a/src/lib/net/FingerprintDatabase.h b/src/lib/net/FingerprintDatabase.h index 4a17696e..49272650 100644 --- a/src/lib/net/FingerprintDatabase.h +++ b/src/lib/net/FingerprintDatabase.h @@ -19,6 +19,7 @@ #define BARRIER_LIB_NET_FINGERPRINT_DATABASE_H #include "FingerprintData.h" +#include "io/filesystem.h" #include #include #include @@ -27,8 +28,8 @@ namespace barrier { class FingerprintDatabase { public: - void read(const std::string& path); - void write(const std::string& path); + void read(const fs::path& path); + void write(const fs::path& path); void read_stream(std::istream& stream); void write_stream(std::ostream& stream); diff --git a/src/lib/net/SecureListenSocket.cpp b/src/lib/net/SecureListenSocket.cpp index 2a9f84cb..71e09ce5 100644 --- a/src/lib/net/SecureListenSocket.cpp +++ b/src/lib/net/SecureListenSocket.cpp @@ -25,13 +25,6 @@ #include "common/DataDirectories.h" #include "base/String.h" -static const char s_certificateDir[] = { "SSL" }; -static const char s_certificateFilename[] = { "Barrier.pem" }; - -// -// SecureListenSocket -// - SecureListenSocket::SecureListenSocket( IEventQueue* events, SocketMultiplexer* socketMultiplexer, @@ -55,12 +48,7 @@ SecureListenSocket::accept() setListeningJob(); } - std::string certificateFilename = barrier::string::sprintf("%s/%s/%s", - DataDirectories::profile().c_str(), - s_certificateDir, - s_certificateFilename); - - bool loaded = socket->loadCertificates(certificateFilename); + bool loaded = socket->load_certificates(barrier::DataDirectories::ssl_certificate_path()); if (!loaded) { delete socket; return NULL; diff --git a/src/lib/net/SecureSocket.cpp b/src/lib/net/SecureSocket.cpp index 3c65d9ac..6a658db1 100644 --- a/src/lib/net/SecureSocket.cpp +++ b/src/lib/net/SecureSocket.cpp @@ -26,7 +26,7 @@ #include "base/Log.h" #include "base/String.h" #include "common/DataDirectories.h" -#include "io/fstream.h" +#include "io/filesystem.h" #include "net/FingerprintDatabase.h" #include @@ -327,39 +327,35 @@ SecureSocket::initSsl(bool server) initContext(server); } -bool SecureSocket::loadCertificates(const std::string& filename) +bool SecureSocket::load_certificates(const barrier::fs::path& path) { - if (filename.empty()) { + if (path.empty()) { showError("ssl certificate is not specified"); return false; } else { - std::ifstream file(filename.c_str()); - bool exist = file.good(); - file.close(); - - if (!exist) { - showError("ssl certificate doesn't exist: " + filename); + if (!barrier::fs::is_regular_file(path)) { + showError("ssl certificate doesn't exist: " + path.u8string()); return false; } } int r = 0; - r = SSL_CTX_use_certificate_file(m_ssl->m_context, filename.c_str(), SSL_FILETYPE_PEM); + r = SSL_CTX_use_certificate_file(m_ssl->m_context, path.u8string().c_str(), SSL_FILETYPE_PEM); if (r <= 0) { - showError("could not use ssl certificate: " + filename); + showError("could not use ssl certificate: " + path.u8string()); return false; } - r = SSL_CTX_use_PrivateKey_file(m_ssl->m_context, filename.c_str(), SSL_FILETYPE_PEM); + r = SSL_CTX_use_PrivateKey_file(m_ssl->m_context, path.u8string().c_str(), SSL_FILETYPE_PEM); if (r <= 0) { - showError("could not use ssl private key: " + filename); + showError("could not use ssl private key: " + path.u8string()); return false; } r = SSL_CTX_check_private_key(m_ssl->m_context); if (!r) { - showError("could not verify ssl private key: " + filename); + showError("could not verify ssl private key: " + path.u8string()); return false; } @@ -674,20 +670,20 @@ SecureSocket::verifyCertFingerprint() barrier::format_ssl_fingerprint(fingerprint_sha1.data).c_str(), barrier::format_ssl_fingerprint(fingerprint_sha256.data).c_str())); - auto fingerprint_db_path = DataDirectories::trusted_servers_ssl_fingerprints_path(); + auto fingerprint_db_path = barrier::DataDirectories::trusted_servers_ssl_fingerprints_path(); // Provide debug hint as to what file is being used to verify fingerprint trust - LOG((CLOG_NOTE "fingerprint_db_path: %s", fingerprint_db_path.c_str())); + LOG((CLOG_NOTE "fingerprint_db_path: %s", fingerprint_db_path.u8string().c_str())); barrier::FingerprintDatabase db; db.read(fingerprint_db_path); if (!db.fingerprints().empty()) { LOG((CLOG_NOTE "Read %d fingerprints from: %s", db.fingerprints().size(), - fingerprint_db_path.c_str())); + fingerprint_db_path.u8string().c_str())); } else { LOG((CLOG_NOTE "Could not read fingerprints from: %s", - fingerprint_db_path.c_str())); + fingerprint_db_path.u8string().c_str())); } if (db.is_trusted(fingerprint_sha256)) { diff --git a/src/lib/net/SecureSocket.h b/src/lib/net/SecureSocket.h index 24653b6f..6e355008 100644 --- a/src/lib/net/SecureSocket.h +++ b/src/lib/net/SecureSocket.h @@ -19,6 +19,7 @@ #include "net/TCPSocket.h" #include "net/XSocket.h" +#include "io/filesystem.h" class IEventQueue; class SocketMultiplexer; @@ -55,7 +56,7 @@ public: EJobResult doRead() override; EJobResult doWrite() override; void initSsl(bool server); - bool loadCertificates(const std::string& filename); + bool load_certificates(const barrier::fs::path& path); private: // SSL diff --git a/src/lib/net/SecureUtils.cpp b/src/lib/net/SecureUtils.cpp index b99dd38c..3dd2a6a8 100644 --- a/src/lib/net/SecureUtils.cpp +++ b/src/lib/net/SecureUtils.cpp @@ -46,7 +46,7 @@ #include "SecureUtils.h" #include "base/String.h" #include "base/finally.h" -#include "io/fstream.h" +#include "io/filesystem.h" #include #include diff --git a/src/lib/platform/MSWindowsHook.cpp b/src/lib/platform/MSWindowsHook.cpp index b10d5c63..3230d24c 100644 --- a/src/lib/platform/MSWindowsHook.cpp +++ b/src/lib/platform/MSWindowsHook.cpp @@ -574,7 +574,7 @@ MSWindowsHook::install() g_fakeServerInput = false; // setup immune keys - g_immuneKeysPath = DataDirectories::profile() + "\\ImmuneKeys.txt"; + g_immuneKeysPath = (barrier::DataDirectories::profile() / "ImmuneKeys.txt").u8string(); g_immuneKeys = immune_keys_list(); LOG((CLOG_DEBUG "Found %u immune keys in %s", g_immuneKeys.size(), g_immuneKeysPath.c_str()));