gui: Use new FingerprintDatabase to handle fingerprints

This commit is contained in:
Povilas Kanapickas 2021-11-01 02:52:45 +02:00
parent 9cac96b4af
commit be8ba0d132
8 changed files with 87 additions and 215 deletions

View File

@ -29,7 +29,6 @@ set(GUI_SOURCE_FILES
src/CommandProcess.cpp src/CommandProcess.cpp
src/DataDownloader.cpp src/DataDownloader.cpp
src/DisplayIsValid.cpp src/DisplayIsValid.cpp
src/Fingerprint.cpp
src/HotkeyDialog.cpp src/HotkeyDialog.cpp
src/IpcClient.cpp src/IpcClient.cpp
src/Ipc.cpp src/Ipc.cpp
@ -70,7 +69,6 @@ set(GUI_HEADER_FILES
src/DataDownloader.h src/DataDownloader.h
src/DisplayIsValid.h src/DisplayIsValid.h
src/ElevateMode.h src/ElevateMode.h
src/Fingerprint.h
src/HotkeyDialog.h src/HotkeyDialog.h
src/IpcClient.h src/IpcClient.h
src/Ipc.h src/Ipc.h

View File

@ -1,147 +0,0 @@
/*
* barrier -- mouse and keyboard sharing utility
* Copyright (C) 2015-2016 Symless Ltd.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "Fingerprint.h"
#include "common/DataDirectories.h"
#include <QDir>
#include <QTextStream>
static const char kDirName[] = "SSL/Fingerprints";
static const char kLocalFilename[] = "Local.txt";
static const char kTrustedServersFilename[] = "TrustedServers.txt";
static const char kTrustedClientsFilename[] = "TrustedClients.txt";
Fingerprint::Fingerprint(const QString& filename)
{
m_Filename = filename;
}
void Fingerprint::trust(const QString& fingerprintText, bool append)
{
Fingerprint::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 Fingerprint::fileExists() const
{
QString dirName = Fingerprint::directoryPath();
if (!QDir(dirName).exists()) {
return false;
}
QFile file(filePath());
return file.exists();
}
bool Fingerprint::isTrusted(const QString& fingerprintText)
{
QStringList list = readList();
for (QString trusted : list) {
if (trusted == fingerprintText) {
return true;
}
}
return false;
}
QStringList Fingerprint::readList(const int readTo)
{
QStringList list;
QString dirName = Fingerprint::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 Fingerprint::readFirst()
{
QStringList list = readList(1);
return list.at(0);
}
QString Fingerprint::filePath() const
{
QString dir = Fingerprint::directoryPath();
return QString("%1/%2").arg(dir).arg(m_Filename);
}
void Fingerprint::persistDirectory()
{
QDir dir(Fingerprint::directoryPath());
if (!dir.exists()) {
dir.mkpath(".");
}
}
QString Fingerprint::directoryPath()
{
auto profileDir = QString::fromStdString(DataDirectories::profile());
return QString("%1/%2")
.arg(profileDir)
.arg(kDirName);
}
Fingerprint Fingerprint::local()
{
return Fingerprint(kLocalFilename);
}
Fingerprint Fingerprint::trustedServers()
{
return Fingerprint(kTrustedServersFilename);
}
Fingerprint Fingerprint::trustedClients()
{
return Fingerprint(kTrustedClientsFilename);
}

View File

@ -1,42 +0,0 @@
/*
* barrier -- mouse and keyboard sharing utility
* Copyright (C) 2015-2016 Symless Ltd.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QString>
class Fingerprint
{
public:
void trust(const QString& fingerprintText, bool append = true);
bool isTrusted(const QString& fingerprintText);
QStringList readList(const int readTo = -1);
QString readFirst();
QString filePath() const;
bool fileExists() const;
static Fingerprint local();
static Fingerprint trustedServers();
static Fingerprint trustedClients();
static QString directoryPath();
static void persistDirectory();
private:
Fingerprint(const QString& filename);
QString m_Filename;
};

View File

@ -20,7 +20,6 @@
#include "MainWindow.h" #include "MainWindow.h"
#include "Fingerprint.h"
#include "AboutDialog.h" #include "AboutDialog.h"
#include "ServerConfigDialog.h" #include "ServerConfigDialog.h"
#include "SettingsDialog.h" #include "SettingsDialog.h"
@ -31,7 +30,10 @@
#include "ProcessorArch.h" #include "ProcessorArch.h"
#include "SslCertificate.h" #include "SslCertificate.h"
#include "ShutdownCh.h" #include "ShutdownCh.h"
#include "base/String.h"
#include "common/DataDirectories.h" #include "common/DataDirectories.h"
#include "net/FingerprintDatabase.h"
#include "net/SecureUtils.h"
#include <QtCore> #include <QtCore>
#include <QtGui> #include <QtGui>
@ -417,11 +419,21 @@ void MainWindow::checkFingerprint(const QString& line)
return; return;
} }
QString fingerprint = fingerprintRegex.cap(1); barrier::FingerprintData fingerprint = {
if (Fingerprint::trustedServers().isTrusted(fingerprint)) { barrier::fingerprint_type_to_string(barrier::FingerprintType::SHA1),
barrier::string::from_hex(fingerprintRegex.cap(1).toStdString())
};
auto db_path = DataDirectories::trusted_servers_ssl_fingerprints_path();
barrier::FingerprintDatabase db;
db.read(db_path);
if (db.is_trusted(fingerprint)) {
return; return;
} }
auto formatted_fingerprint = barrier::format_ssl_fingerprint(fingerprint.data);
static bool messageBoxAlreadyShown = false; static bool messageBoxAlreadyShown = false;
if (!messageBoxAlreadyShown) { if (!messageBoxAlreadyShown) {
@ -440,12 +452,13 @@ void MainWindow::checkFingerprint(const QString& line)
"To automatically trust this fingerprint for future " "To automatically trust this fingerprint for future "
"connections, click Yes. To reject this fingerprint and " "connections, click Yes. To reject this fingerprint and "
"disconnect from the server, click No.") "disconnect from the server, click No.")
.arg(fingerprint), .arg(QString::fromStdString(formatted_fingerprint)),
QMessageBox::Yes | QMessageBox::No); QMessageBox::Yes | QMessageBox::No);
if (fingerprintReply == QMessageBox::Yes) { if (fingerprintReply == QMessageBox::Yes) {
// restart core process after trusting fingerprint. // restart core process after trusting fingerprint.
Fingerprint::trustedServers().trust(fingerprint); db.add_trusted(fingerprint);
db.write(db_path);
startBarrier(); startBarrier();
} }
@ -965,12 +978,29 @@ void MainWindow::updateSSLFingerprint()
}); });
m_pSslCertificate->generateCertificate(); m_pSslCertificate->generateCertificate();
} }
if (m_AppConfig->getCryptoEnabled() && Fingerprint::local().fileExists()) {
m_pLabelLocalFingerprint->setText(Fingerprint::local().readFirst());
m_pLabelLocalFingerprint->setTextInteractionFlags(Qt::TextSelectableByMouse);
} else {
m_pLabelLocalFingerprint->setText("Disabled"); m_pLabelLocalFingerprint->setText("Disabled");
if (!m_AppConfig->getCryptoEnabled()) {
return;
} }
auto local_path = DataDirectories::local_ssl_fingerprints_path();
if (!QFile::exists(QString::fromStdString(local_path))) {
return;
}
barrier::FingerprintDatabase db;
db.read(local_path);
if (db.fingerprints().empty()) {
return;
}
const auto& fingerprint = db.fingerprints().front();
auto formatted_fingerprint = barrier::format_ssl_fingerprint(fingerprint.data);
m_pLabelLocalFingerprint->setText(QString::fromStdString(formatted_fingerprint));
m_pLabelLocalFingerprint->setTextInteractionFlags(Qt::TextSelectableByMouse);
} }
void MainWindow::on_m_pGroupClient_toggled(bool on) void MainWindow::on_m_pGroupClient_toggled(bool on)

View File

@ -16,8 +16,8 @@
*/ */
#include "SslCertificate.h" #include "SslCertificate.h"
#include "Fingerprint.h"
#include "common/DataDirectories.h" #include "common/DataDirectories.h"
#include "net/FingerprintDatabase.h"
#include "net/SecureUtils.h" #include "net/SecureUtils.h"
#include <QProcess> #include <QProcess>
@ -44,17 +44,17 @@ SslCertificate::SslCertificate(QObject *parent) :
void SslCertificate::generateCertificate() void SslCertificate::generateCertificate()
{ {
auto filename = QString::fromStdString(getCertificatePath()); auto cert_path = getCertificatePath();
QFile file(filename); QFile file(QString::fromStdString(cert_path));
if (!file.exists() || !isCertificateValid(filename)) { if (!file.exists() || !isCertificateValid(cert_path)) {
QDir sslDir(QString::fromStdString(getCertificateDirectory())); QDir sslDir(QString::fromStdString(getCertificateDirectory()));
if (!sslDir.exists()) { if (!sslDir.exists()) {
sslDir.mkpath("."); sslDir.mkpath(".");
} }
try { try {
barrier::generate_pem_self_signed_cert(filename.toStdString()); barrier::generate_pem_self_signed_cert(cert_path);
} catch (const std::exception& e) { } catch (const std::exception& e) {
emit error(QString("SSL tool failed: %1").arg(e.what())); emit error(QString("SSL tool failed: %1").arg(e.what()));
return; return;
@ -63,18 +63,22 @@ void SslCertificate::generateCertificate()
emit info(tr("SSL certificate generated.")); emit info(tr("SSL certificate generated."));
} }
generateFingerprint(filename); generateFingerprint(cert_path);
emit generateFinished(); emit generateFinished();
} }
void SslCertificate::generateFingerprint(const QString& certificateFilename) void SslCertificate::generateFingerprint(const std::string& cert_path)
{ {
try { try {
auto fingerprint = barrier::get_pem_file_cert_fingerprint(certificateFilename.toStdString(), auto fingerprint = barrier::get_pem_file_cert_fingerprint(cert_path,
barrier::FingerprintType::SHA1); barrier::FingerprintType::SHA1);
Fingerprint::local().trust(QString::fromStdString(
barrier::format_ssl_fingerprint(fingerprint)), false); auto local_path = DataDirectories::local_ssl_fingerprints_path();
barrier::FingerprintDatabase db;
db.add_trusted(barrier::FingerprintData{"sha1", fingerprint});
db.write(local_path);
emit info(tr("SSL fingerprint generated.")); emit info(tr("SSL fingerprint generated."));
} catch (const std::exception& e) { } catch (const std::exception& e) {
emit error(tr("Failed to find SSL fingerprint.") + e.what()); emit error(tr("Failed to find SSL fingerprint.") + e.what());
@ -91,7 +95,7 @@ std::string SslCertificate::getCertificateDirectory()
return m_ProfileDir + QDir::separator().toLatin1() + kSslDir; return m_ProfileDir + QDir::separator().toLatin1() + kSslDir;
} }
bool SslCertificate::isCertificateValid(const QString& path) bool SslCertificate::isCertificateValid(const std::string& path)
{ {
OpenSSL_add_all_algorithms(); OpenSSL_add_all_algorithms();
ERR_load_BIO_strings(); ERR_load_BIO_strings();
@ -99,7 +103,7 @@ bool SslCertificate::isCertificateValid(const QString& path)
BIO* bio = BIO_new(BIO_s_file()); BIO* bio = BIO_new(BIO_s_file());
auto ret = BIO_read_filename(bio, path.toStdString().c_str()); auto ret = BIO_read_filename(bio, path.c_str());
if (!ret) { if (!ret) {
emit info(tr("Could not read from default certificate file.")); emit info(tr("Could not read from default certificate file."));
BIO_free_all(bio); BIO_free_all(bio);

View File

@ -37,12 +37,12 @@ signals:
private: private:
std::pair<bool, std::string> runTool(const QStringList& args); std::pair<bool, std::string> runTool(const QStringList& args);
void generateFingerprint(const QString& certificateFilename); void generateFingerprint(const std::string& cert_path);
std::string getCertificatePath(); std::string getCertificatePath();
std::string getCertificateDirectory(); std::string getCertificateDirectory();
bool isCertificateValid(const QString& path); bool isCertificateValid(const std::string& path);
private: private:
std::string m_ProfileDir; std::string m_ProfileDir;
}; };

View File

@ -31,6 +31,10 @@ public:
static const std::string& systemconfig(); static const std::string& systemconfig();
static const std::string& systemconfig(const std::string& path); static const std::string& systemconfig(const std::string& 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();
private: private:
static std::string _profile; static std::string _profile;
static std::string _global; static std::string _global;

View File

@ -21,3 +21,28 @@
std::string DataDirectories::_profile; std::string DataDirectories::_profile;
std::string DataDirectories::_global; std::string DataDirectories::_global;
std::string DataDirectories::_systemconfig; std::string 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()
{
return profile() + "/" + kFingerprintsDirName;
}
std::string DataDirectories::local_ssl_fingerprints_path()
{
return ssl_fingerprints_path() + "/" + kFingerprintsLocalFilename;
}
std::string DataDirectories::trusted_servers_ssl_fingerprints_path()
{
return ssl_fingerprints_path() + "/" + kFingerprintsTrustedServersFilename;
}
std::string DataDirectories::trusted_clients_ssl_fingerprints_path()
{
return ssl_fingerprints_path() + "/" + kFingerprintsTrustedClientsFilename;
}