refactor: secureutils add pemFileCertFingerprint

This commit is contained in:
sithlord48 2025-01-29 00:22:48 -05:00 committed by Nick Bolton
parent fb32f141cc
commit 5a71d63923
8 changed files with 163 additions and 24 deletions

View file

@ -11,6 +11,7 @@ add_library(base STATIC
EventQueue.h
EventTypes.cpp
EventTypes.h
finally.h
FunctionEventJob.cpp
FunctionEventJob.h
FunctionJob.cpp

53
src/lib/base/finally.h Normal file
View file

@ -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 <utility>
namespace deskflow {
/**
* @brief The `FinalAction` class implements a common pattern for calling an action at the end of a function.
*/
template <class Callable> 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 <class Callable> inline FinalAction<Callable> finally(Callable &&callable) noexcept
{
return FinalAction<Callable>(std::forward<Callable>(callable));
}
} // namespace deskflow

View file

@ -9,6 +9,7 @@
#include "TlsFingerprint.h"
#include "common/constants.h"
#include "net/SecureUtils.h"
#include <QCoreApplication>
#include <QDir>
@ -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;
}
}

View file

@ -1,9 +1,11 @@
# SPDX-FileCopyrightText: 2024 Chris Rizzitello <sithlord48@gmail.com>
# SPDX-FileCopyrightText: 2024 - 2025 Chris Rizzitello <sithlord48@gmail.com>
# 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

52
src/lib/io/filesystem.cpp Normal file
View file

@ -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 <fstream>
namespace deskflow {
namespace {
template <class Stream> 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

27
src/lib/io/filesystem.h Normal file
View file

@ -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 <cstdio>
#include <filesystem>
#include <ios>
#include <iosfwd>
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

View file

@ -7,6 +7,8 @@
#include "SecureUtils.h"
#include "base/String.h"
#include "base/finally.h"
#include "io/filesystem.h"
#include <openssl/pem.h>
#include <openssl/x509.h>
@ -66,4 +68,20 @@ std::vector<uint8_t> SSLCertFingerprint(X509 *cert, FingerprintType type)
return digestVec;
}
std::vector<std::uint8_t> 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

View file

@ -25,4 +25,6 @@ namespace deskflow {
std::string formatSSLFingerprint(const std::vector<uint8_t> &fingerprint, bool enableSeparators = true);
std::vector<std::uint8_t> SSLCertFingerprint(X509 *cert, FingerprintType type);
std::vector<std::uint8_t> pemFileCertFingerprint(const std::string &path, FingerprintType type);
} // namespace deskflow