refactor: use new Fingerprint database
based-on:50534ecb43based-on:be8ba0d132
This commit is contained in:
parent
298b1047c4
commit
d0d5182425
8 changed files with 83 additions and 196 deletions
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2024 Chris Rizzitello <sithord48@gmail.com>
|
||||
* SPDX-FileCopyrightText: (C) 2024 - 2025 Chris Rizzitello <sithord48@gmail.com>
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2024 Symless Ltd.
|
||||
* SPDX-FileCopyrightText: (C) 2008 Volker Lanz <vl@fidra.de>
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
#include "dialogs/ServerConfigDialog.h"
|
||||
#include "dialogs/SettingsDialog.h"
|
||||
|
||||
#include "base/String.h"
|
||||
#include "common/constants.h"
|
||||
#include "gui/Logger.h"
|
||||
#include "gui/config/ConfigScopes.h"
|
||||
|
|
@ -23,7 +24,9 @@
|
|||
#include "gui/string_utils.h"
|
||||
#include "gui/style_utils.h"
|
||||
#include "gui/styles.h"
|
||||
#include "gui/tls/TlsFingerprint.h"
|
||||
#include "net/FingerprintDatabase.h"
|
||||
#include "net/SecureUtils.h"
|
||||
|
||||
#include "platform/wayland.h"
|
||||
|
||||
#if defined(Q_OS_LINUX)
|
||||
|
|
@ -466,7 +469,29 @@ void MainWindow::updateSize()
|
|||
|
||||
void MainWindow::showMyFingerprint()
|
||||
{
|
||||
QMessageBox::information(this, "TLS fingerprint", TlsFingerprint::local().readFirst());
|
||||
auto localPath = QStringLiteral("%1/%2").arg(getTlsPath(), kFingerprintLocalFilename).toStdString();
|
||||
if (!QFile::exists(QString::fromStdString(localPath))) {
|
||||
QMessageBox::information(
|
||||
this, tr("TLS fingerprint Error"),
|
||||
tr("Unable to read localfinger print: %1\n You may want to regenerate your keys.")
|
||||
.arg(QString::fromStdString(localPath))
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
deskflow::FingerprintDatabase db;
|
||||
db.read(localPath);
|
||||
if (db.fingerprints().empty()) {
|
||||
QMessageBox::information(
|
||||
this, tr("TLS fingerprint Error"),
|
||||
tr("Unable to read localDatabase\n You may want to regenerate your keys.")
|
||||
.arg(QString::fromStdString(localPath))
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto fingerprint = QString::fromStdString(deskflow::formatSSLFingerprint(db.fingerprints().front().data));
|
||||
QMessageBox::information(this, "TLS fingerprint", fingerprint);
|
||||
}
|
||||
|
||||
void MainWindow::setModeServer()
|
||||
|
|
@ -669,8 +694,13 @@ void MainWindow::checkFingerprint(const QString &line)
|
|||
return;
|
||||
}
|
||||
|
||||
auto fingerprint = match.captured(1);
|
||||
if (TlsFingerprint::trustedServers().isTrusted(fingerprint)) {
|
||||
auto localPath = QStringLiteral("%1/%2").arg(getTlsPath(), kFingerprintTrustedServersFilename).toStdString();
|
||||
|
||||
deskflow::FingerprintDatabase db;
|
||||
db.read(localPath);
|
||||
|
||||
const deskflow::FingerprintData fingerprint{"sha1", deskflow::string::fromHex(match.captured(1).toStdString())};
|
||||
if (db.isTrusted(fingerprint)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -690,13 +720,13 @@ void MainWindow::checkFingerprint(const QString &line)
|
|||
"you're expecting (it could be a malicious user).</p>"
|
||||
"<p>Do you want to trust this fingerprint for future "
|
||||
"connections? If you don't, a connection cannot be made.</p>")
|
||||
.arg(fingerprint),
|
||||
.arg(QString::fromStdString(deskflow::formatSSLFingerprint(fingerprint.data))),
|
||||
QMessageBox::Yes | QMessageBox::No
|
||||
);
|
||||
|
||||
if (fingerprintReply == QMessageBox::Yes) {
|
||||
// start core process again after trusting fingerprint.
|
||||
TlsFingerprint::trustedServers().trust(fingerprint);
|
||||
db.addTrusted(fingerprint);
|
||||
db.write(localPath);
|
||||
m_coreProcess.start();
|
||||
}
|
||||
|
||||
|
|
@ -897,7 +927,8 @@ void MainWindow::updateLocalFingerprint()
|
|||
{
|
||||
bool fingerprintExists = false;
|
||||
try {
|
||||
fingerprintExists = TlsFingerprint::local().fileExists();
|
||||
auto localPath = QStringLiteral("%1/%2").arg(getTlsPath(), kFingerprintLocalFilename).toStdString();
|
||||
fingerprintExists = QFile::exists(QString::fromStdString(localPath));
|
||||
} catch (const std::exception &e) {
|
||||
qDebug() << e.what();
|
||||
qFatal() << "failed to check if fingerprint exists";
|
||||
|
|
@ -1026,3 +1057,9 @@ void MainWindow::showAndActivate()
|
|||
m_actionRestore->setVisible(false);
|
||||
m_actionMinimize->setVisible(true);
|
||||
}
|
||||
|
||||
QString MainWindow::getTlsPath()
|
||||
{
|
||||
CoreTool coreTool;
|
||||
return QStringLiteral("%1/%2").arg(coreTool.getProfileDir(), kSslDir);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,6 +164,8 @@ private:
|
|||
void updateStatus();
|
||||
void showAndActivate();
|
||||
|
||||
QString getTlsPath();
|
||||
|
||||
VersionChecker m_versionChecker;
|
||||
bool m_secureSocket = false;
|
||||
deskflow::gui::config::ServerConfigDialogState m_serverConfigDialogState;
|
||||
|
|
|
|||
|
|
@ -29,4 +29,5 @@ const auto kDebugBuild = false;
|
|||
|
||||
const auto kSslDir = "tls";
|
||||
const auto kCertificateFilename = "@CMAKE_PROJECT_NAME@.pem";
|
||||
const auto kFingerprintLocalFilename = "local-fingerprint";
|
||||
const auto kFingerprintTrustedServersFilename = "trusted-servers";
|
||||
|
|
|
|||
|
|
@ -77,8 +77,6 @@ add_library(${target} STATIC
|
|||
proxy/QSettingsProxy.h
|
||||
tls/TlsCertificate.cpp
|
||||
tls/TlsCertificate.h
|
||||
tls/TlsFingerprint.cpp
|
||||
tls/TlsFingerprint.h
|
||||
tls/TlsUtility.cpp
|
||||
tls/TlsUtility.h
|
||||
validators/AliasValidator.cpp
|
||||
|
|
|
|||
|
|
@ -7,9 +7,10 @@
|
|||
|
||||
#include "TlsCertificate.h"
|
||||
|
||||
#include "TlsFingerprint.h"
|
||||
|
||||
#include "common/constants.h"
|
||||
#include "gui/core/CoreTool.h"
|
||||
#include "net/FingerprintData.h"
|
||||
#include "net/FingerprintDatabase.h"
|
||||
#include "net/SecureUtils.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
|
@ -47,7 +48,18 @@ bool TlsCertificate::generateFingerprint(const QString &certificateFilename)
|
|||
try {
|
||||
auto fingerprint =
|
||||
deskflow::pemFileCertFingerprint(certificateFilename.toStdString(), deskflow::FingerprintType::SHA1);
|
||||
TlsFingerprint::local().trust(QString::fromStdString(deskflow::formatSSLFingerprint(fingerprint)), false);
|
||||
|
||||
CoreTool coreTool;
|
||||
QString profileDir = coreTool.getProfileDir();
|
||||
|
||||
auto localPath = QStringLiteral("%1/%2/%3").arg(profileDir, kSslDir, kFingerprintLocalFilename).toStdString();
|
||||
|
||||
const deskflow::FingerprintData data{"sha1", fingerprint};
|
||||
|
||||
deskflow::FingerprintDatabase db;
|
||||
db.addTrusted(data);
|
||||
db.write(localPath);
|
||||
|
||||
qDebug("tls fingerprint generated");
|
||||
return true;
|
||||
} catch (const std::exception &e) {
|
||||
|
|
|
|||
|
|
@ -1,131 +0,0 @@
|
|||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2015 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "TlsFingerprint.h"
|
||||
|
||||
#include "gui/core/CoreTool.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QTextStream>
|
||||
|
||||
// TODO: Reduce duplication of these strings between here and SecureSocket.cpp
|
||||
static const char kDirName[] = "tls";
|
||||
static const char kLocalFilename[] = "local-fingerprint";
|
||||
static const char kTrustedServersFilename[] = "trusted-servers";
|
||||
static const char kTrustedClientsFilename[] = "trusted-clients";
|
||||
|
||||
TlsFingerprint::TlsFingerprint(const QString &filename) : m_Filename(filename)
|
||||
{
|
||||
}
|
||||
|
||||
void TlsFingerprint::trust(const QString &fingerprintText, bool append) const
|
||||
{
|
||||
TlsFingerprint::persistDirectory();
|
||||
|
||||
QIODevice::OpenMode openMode;
|
||||
if (append) {
|
||||
openMode = QIODevice::Append;
|
||||
} else {
|
||||
openMode = QIODevice::WriteOnly;
|
||||
}
|
||||
|
||||
QFile file(filePath());
|
||||
if (file.open(openMode)) {
|
||||
QTextStream out(&file);
|
||||
out << fingerprintText << "\n";
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
bool TlsFingerprint::fileExists() const
|
||||
{
|
||||
QString dirName = TlsFingerprint::directoryPath();
|
||||
if (!QDir(dirName).exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QFile file(filePath());
|
||||
return file.exists();
|
||||
}
|
||||
|
||||
bool TlsFingerprint::isTrusted(const QString &fingerprintText) const
|
||||
{
|
||||
const QStringList list = readList();
|
||||
for (const auto &trusted : list) {
|
||||
if (trusted == fingerprintText) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList TlsFingerprint::readList(const int readTo) const
|
||||
{
|
||||
QStringList list;
|
||||
|
||||
QString dirName = TlsFingerprint::directoryPath();
|
||||
if (!QDir(dirName).exists()) {
|
||||
return list;
|
||||
}
|
||||
|
||||
QFile file(filePath());
|
||||
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
QTextStream in(&file);
|
||||
while (!in.atEnd()) {
|
||||
list.append(in.readLine());
|
||||
if (list.size() == readTo) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
QString TlsFingerprint::readFirst() const
|
||||
{
|
||||
QStringList list = readList(1);
|
||||
return list.at(0);
|
||||
}
|
||||
|
||||
QString TlsFingerprint::filePath() const
|
||||
{
|
||||
QString dir = TlsFingerprint::directoryPath();
|
||||
return QString("%1/%2").arg(dir, m_Filename);
|
||||
}
|
||||
|
||||
void TlsFingerprint::persistDirectory()
|
||||
{
|
||||
QDir dir(TlsFingerprint::directoryPath());
|
||||
if (!dir.exists()) {
|
||||
dir.mkpath(".");
|
||||
}
|
||||
}
|
||||
|
||||
QString TlsFingerprint::directoryPath()
|
||||
{
|
||||
CoreTool coreTool;
|
||||
QString profileDir = coreTool.getProfileDir();
|
||||
|
||||
return QString("%1/%2").arg(profileDir, kDirName);
|
||||
}
|
||||
|
||||
TlsFingerprint TlsFingerprint::local()
|
||||
{
|
||||
return TlsFingerprint(kLocalFilename);
|
||||
}
|
||||
|
||||
TlsFingerprint TlsFingerprint::trustedServers()
|
||||
{
|
||||
return TlsFingerprint(kTrustedServersFilename);
|
||||
}
|
||||
|
||||
TlsFingerprint TlsFingerprint::trustedClients()
|
||||
{
|
||||
return TlsFingerprint(kTrustedClientsFilename);
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2015 Symless Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
|
||||
class TlsFingerprint
|
||||
{
|
||||
private:
|
||||
explicit TlsFingerprint(const QString &filename);
|
||||
|
||||
public:
|
||||
static TlsFingerprint local();
|
||||
static TlsFingerprint trustedServers();
|
||||
static TlsFingerprint trustedClients();
|
||||
static QString directoryPath();
|
||||
static QString localFingerprint();
|
||||
static bool localFingerprintExists();
|
||||
static void persistDirectory();
|
||||
|
||||
void trust(const QString &fingerprintText, bool append = true) const;
|
||||
bool isTrusted(const QString &fingerprintText) const;
|
||||
QStringList readList(const int readTo = -1) const;
|
||||
QString readFirst() const;
|
||||
QString filePath() const;
|
||||
bool fileExists() const;
|
||||
|
||||
private:
|
||||
QString m_Filename;
|
||||
};
|
||||
|
|
@ -15,6 +15,7 @@
|
|||
#include "base/TMethodEventJob.h"
|
||||
#include "common/constants.h"
|
||||
#include "mt/Lock.h"
|
||||
#include "net/FingerprintDatabase.h"
|
||||
#include "net/TCPSocket.h"
|
||||
#include "net/TSocketMultiplexerMethodJob.h"
|
||||
#include <net/InverseSockets/SslLogger.h>
|
||||
|
|
@ -621,34 +622,35 @@ bool SecureSocket::verifyCertFingerprint()
|
|||
return false;
|
||||
}
|
||||
|
||||
auto fingerprint = deskflow::formatSSLFingerprint(fingerprint_raw);
|
||||
LOG((CLOG_NOTE "server fingerprint: %s", fingerprint.c_str()));
|
||||
LOG((CLOG_NOTE "server fingerprint: %s", deskflow::formatSSLFingerprint(fingerprint_raw).c_str()));
|
||||
|
||||
std::string trustedServersFilename;
|
||||
trustedServersFilename = deskflow::string::sprintf(
|
||||
std::string trustedServersFilename = deskflow::string::sprintf(
|
||||
"%s/%s/%s", ARCH->getProfileDirectory().c_str(), kSslDir, kFingerprintTrustedServersFilename
|
||||
);
|
||||
|
||||
// check if this fingerprint exist
|
||||
std::string fileLine;
|
||||
std::ifstream file;
|
||||
file.open(deskflow::filesystem::path(trustedServersFilename));
|
||||
|
||||
bool isValid = false;
|
||||
if (file.is_open()) {
|
||||
while (!file.eof()) {
|
||||
getline(file, fileLine);
|
||||
if (!fileLine.empty() && !fileLine.compare(fingerprint)) {
|
||||
isValid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
deskflow::openUtf8Path(file, trustedServersFilename);
|
||||
deskflow::FingerprintDatabase db;
|
||||
db.read(trustedServersFilename);
|
||||
if (!db.fingerprints().empty()) {
|
||||
LOG((CLOG_NOTE "read %d fingerprints from %s", db.fingerprints().size(), trustedServersFilename.c_str()));
|
||||
} else {
|
||||
LOG((CLOG_ERR "fail to open trusted fingerprints file: %s", trustedServersFilename.c_str()));
|
||||
LOG((CLOG_ERR "failed to open trusted fingerprints file: %s", trustedServersFilename.c_str()));
|
||||
return false;
|
||||
}
|
||||
|
||||
file.close();
|
||||
return isValid;
|
||||
deskflow::FingerprintData fingerprint{"sha1", fingerprint_raw};
|
||||
|
||||
if (!db.isTrusted(fingerprint)) {
|
||||
LOG((CLOG_WARN "fingerprint does not match trusted fingerprint"));
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG((CLOG_NOTE "fingerprint matches trusted fingerprint"));
|
||||
return true;
|
||||
}
|
||||
|
||||
ISocketMultiplexerJob *SecureSocket::serviceConnect(ISocketMultiplexerJob *job, bool, bool write, bool error)
|
||||
|
|
|
|||
Loading…
Reference in a new issue