diff --git a/src/lib/base/CMakeLists.txt b/src/lib/base/CMakeLists.txt index ab54b91d9..37e9b37ae 100644 --- a/src/lib/base/CMakeLists.txt +++ b/src/lib/base/CMakeLists.txt @@ -11,6 +11,7 @@ add_library(base STATIC EventQueue.h EventTypes.cpp EventTypes.h + finally.h FunctionEventJob.cpp FunctionEventJob.h FunctionJob.cpp diff --git a/src/lib/base/finally.h b/src/lib/base/finally.h new file mode 100644 index 000000000..d77cb4851 --- /dev/null +++ b/src/lib/base/finally.h @@ -0,0 +1,53 @@ +/* + * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2025 Deskflow Developers + * SPDX-FileCopyrightText: (C) 2021 Barrier Contributors + * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception + */ + +#pragma once + +#include + +namespace deskflow { + +/** + * @brief The `FinalAction` class implements a common pattern for calling an action at the end of a function. + */ +template class FinalAction +{ +public: + FinalAction() noexcept + { + } + + FinalAction(Callable callable) noexcept : m_callable{callable} + { + } + + ~FinalAction() noexcept + { + if (!m_invoked) { + m_callable(); + } + } + + FinalAction(FinalAction &&other) noexcept : m_callable{std::move(other.m_callable)} + { + std::swap(m_invoked, other.m_invoked); + } + + FinalAction(const FinalAction &) = delete; + FinalAction &operator=(const FinalAction &) = delete; + +private: + bool m_invoked = false; + Callable m_callable; +}; + +template inline FinalAction finally(Callable &&callable) noexcept +{ + return FinalAction(std::forward(callable)); +} + +} // namespace deskflow diff --git a/src/lib/gui/tls/TlsCertificate.cpp b/src/lib/gui/tls/TlsCertificate.cpp index bafb82546..90ed41192 100644 --- a/src/lib/gui/tls/TlsCertificate.cpp +++ b/src/lib/gui/tls/TlsCertificate.cpp @@ -9,6 +9,7 @@ #include "TlsFingerprint.h" #include "common/constants.h" +#include "net/SecureUtils.h" #include #include @@ -184,31 +185,14 @@ bool TlsCertificate::generateCertificate(const QString &path, int keyLength) bool TlsCertificate::generateFingerprint(const QString &certificateFilename) { qDebug("generating tls fingerprint"); - - QStringList arguments; - arguments.append("x509"); - arguments.append("-fingerprint"); - arguments.append(kCertificateHashAlgorithm); - arguments.append("-noout"); - arguments.append("-in"); - arguments.append(certificateFilename); - - if (!runTool(arguments)) { - qCritical("failed to generate tls fingerprint"); - return false; - } - - // find the fingerprint from the tool output - auto i = m_toolStdout.indexOf("="); - if (i != -1) { - i++; - QString fingerprint = m_toolStdout.mid(i, m_toolStdout.size() - i); - - TlsFingerprint::local().trust(fingerprint, false); + try { + auto fingerprint = + deskflow::pemFileCertFingerprint(certificateFilename.toStdString(), deskflow::FingerprintType::SHA1); + TlsFingerprint::local().trust(QString::fromStdString(deskflow::formatSSLFingerprint(fingerprint)), false); qDebug("tls fingerprint generated"); return true; - } else { - qCritical("failed to find tls fingerprint in tls tool output"); + } catch (const std::exception &e) { + qCritical() << "failed to find tls fingerprint: " << e.what(); return false; } } diff --git a/src/lib/io/CMakeLists.txt b/src/lib/io/CMakeLists.txt index 0f6adac25..4e8e8d736 100644 --- a/src/lib/io/CMakeLists.txt +++ b/src/lib/io/CMakeLists.txt @@ -1,9 +1,11 @@ -# SPDX-FileCopyrightText: 2024 Chris Rizzitello +# SPDX-FileCopyrightText: 2024 - 2025 Chris Rizzitello # SPDX-FileCopyrightText: 2012 - 2024 Symless Ltd # SPDX-FileCopyrightText: 2009 - 2012 Nick Bolton # SPDX-License-Identifier: MIT add_library(io STATIC + filesystem.cpp + filesystem.h IStream.h StreamBuffer.cpp StreamBuffer.h diff --git a/src/lib/io/filesystem.cpp b/src/lib/io/filesystem.cpp new file mode 100644 index 000000000..9dce63726 --- /dev/null +++ b/src/lib/io/filesystem.cpp @@ -0,0 +1,52 @@ +/* + * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2025 Deskflow Developers + * SPDX-FileCopyrightText: (C) 2021 Barrier Contributors + * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception + */ + +#include "filesystem.h" + +#include "common/common.h" + +#include + +namespace deskflow { + +namespace { + +template void openUtf8PathImpl(Stream &stream, const fs::path &path, std::ios_base::openmode mode) +{ + stream.open(path.native().c_str(), mode); +} + +} // namespace + +void openUtf8Path(std::ifstream &stream, const fs::path &path, std::ios_base::openmode mode) +{ + openUtf8PathImpl(stream, path, mode); +} + +void openUtf8Path(std::ofstream &stream, const fs::path &path, std::ios_base::openmode mode) +{ + openUtf8PathImpl(stream, path, mode); +} + +void openUtf8Path(std::fstream &stream, const fs::path &path, std::ios_base::openmode mode) +{ + openUtf8PathImpl(stream, path, mode); +} + +std::FILE *fopenUtf8Path(const fs::path &path, const std::string &mode) +{ +#if SYSAPI_WIN32 + std::wstring wpath = path.native(); + std::wstring wmode(mode.begin(), mode.end()); + + return _wfopen(wpath.c_str(), wmode.c_str()); +#else + return std::fopen(path.native().c_str(), mode.c_str()); +#endif +} + +} // namespace deskflow diff --git a/src/lib/io/filesystem.h b/src/lib/io/filesystem.h new file mode 100644 index 000000000..96ddecff2 --- /dev/null +++ b/src/lib/io/filesystem.h @@ -0,0 +1,27 @@ +/* + * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2025 Deskflow Developers + * SPDX-FileCopyrightText: (C) 2021 Barrier Contributors + * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception + */ + +#pragma once + +#include +#include +#include +#include + +namespace deskflow { + +namespace fs = std::filesystem; + +void openUtf8Path(std::ifstream &stream, const fs::path &path, std::ios_base::openmode mode = std::ios_base::in); +void openUtf8Path(std::ofstream &stream, const fs::path &path, std::ios_base::openmode mode = std::ios_base::out); +void openUtf8Path( + std::fstream &stream, const fs::path &path, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out +); + +std::FILE *fopenUtf8Path(const fs::path &path, const std::string &mode); + +} // namespace deskflow diff --git a/src/lib/net/SecureUtils.cpp b/src/lib/net/SecureUtils.cpp index 7fbefb07e..eecb4249f 100644 --- a/src/lib/net/SecureUtils.cpp +++ b/src/lib/net/SecureUtils.cpp @@ -7,6 +7,8 @@ #include "SecureUtils.h" #include "base/String.h" +#include "base/finally.h" +#include "io/filesystem.h" #include #include @@ -66,4 +68,20 @@ std::vector SSLCertFingerprint(X509 *cert, FingerprintType type) return digestVec; } +std::vector pemFileCertFingerprint(const std::string &path, FingerprintType type) +{ + auto fp = fopenUtf8Path(path, "r"); + if (!fp) { + throw std::runtime_error("could not open certificate path"); + } + auto fileClose = finally([fp]() { std::fclose(fp); }); + + X509 *cert = PEM_read_X509(fp, nullptr, nullptr, nullptr); + if (!cert) { + throw std::runtime_error("certificate could not be parsed"); + } + auto certFree = finally([cert]() { X509_free(cert); }); + + return SSLCertFingerprint(cert, type); +} } // namespace deskflow diff --git a/src/lib/net/SecureUtils.h b/src/lib/net/SecureUtils.h index 804788829..d64656f77 100644 --- a/src/lib/net/SecureUtils.h +++ b/src/lib/net/SecureUtils.h @@ -25,4 +25,6 @@ namespace deskflow { std::string formatSSLFingerprint(const std::vector &fingerprint, bool enableSeparators = true); std::vector SSLCertFingerprint(X509 *cert, FingerprintType type); + +std::vector pemFileCertFingerprint(const std::string &path, FingerprintType type); } // namespace deskflow