refactor: do not write sha1 to localdb and no longer send sha1 as part of comparison

This commit is contained in:
sithlord48 2025-05-12 20:23:00 -04:00 committed by Nick Bolton
parent 63e87c16d1
commit 332e6c4a4d
10 changed files with 63 additions and 106 deletions

View file

@ -34,7 +34,6 @@ const auto kDebugBuild = false;
#endif #endif
const auto kTlsDirName = "tls"; const auto kTlsDirName = "tls";
const auto kTlsDbSize = 2;
const auto kTlsCertificateFilename = "@CMAKE_PROJECT_NAME@.pem"; const auto kTlsCertificateFilename = "@CMAKE_PROJECT_NAME@.pem";
const auto kTlsFingerprintLocalFilename = "local-fingerprint"; const auto kTlsFingerprintLocalFilename = "local-fingerprint";
const auto kTlsFingerprintTrustedServersFilename = "trusted-servers"; const auto kTlsFingerprintTrustedServersFilename = "trusted-servers";

View file

@ -153,7 +153,7 @@ MainWindow::MainWindow()
FingerprintDatabase db; FingerprintDatabase db;
db.read(Settings::tlsLocalDb()); db.read(Settings::tlsLocalDb());
if (db.fingerprints().size() != kTlsDbSize) { if (db.fingerprints().isEmpty()) {
regenerateLocalFingerprints(); regenerateLocalFingerprints();
} }
} }
@ -543,13 +543,21 @@ void MainWindow::showMyFingerprint()
FingerprintDatabase db; FingerprintDatabase db;
db.read(Settings::tlsLocalDb()); db.read(Settings::tlsLocalDb());
if (db.fingerprints().size() != kTlsDbSize) { if (db.fingerprints().isEmpty()) {
if (regenerateLocalFingerprints()) if (regenerateLocalFingerprints())
showMyFingerprint(); showMyFingerprint();
return; return;
} }
FingerprintDialog fingerprintDialog(this, db.fingerprints()); Fingerprint sha256Print;
for (const auto &f : std::as_const(db.fingerprints())) {
if (f.type == Fingerprint::Type::SHA256) {
sha256Print = f;
break;
}
}
FingerprintDialog fingerprintDialog(this, sha256Print);
fingerprintDialog.exec(); fingerprintDialog.exec();
} }
@ -762,20 +770,18 @@ void MainWindow::checkConnected(const QString &line)
void MainWindow::checkFingerprint(const QString &line) void MainWindow::checkFingerprint(const QString &line)
{ {
static const QRegularExpression re(R"(.*peer fingerprint: \(SHA1\) ([A-F0-9:]+) \(SHA256\) ([A-F0-9:]+))"); static const auto tlsPeerMessage = QStringLiteral("peer fingerprint: ");
auto match = re.match(line); static const qsizetype msgLen = QString(tlsPeerMessage).length();
if (!match.hasMatch()) {
const qsizetype midStart = line.indexOf(tlsPeerMessage);
if (midStart == -1)
return; return;
}
const Fingerprint sha1 = {Fingerprint::Type::SHA1, QByteArray::fromHex(match.captured(1).remove(":").toLatin1())}; const auto sha256Text = line.mid(midStart + msgLen).remove(':');
const auto sha256Text = match.captured(2); const Fingerprint sha256 = {Fingerprint::Type::SHA256, QByteArray::fromHex(sha256Text.toLatin1())};
const Fingerprint sha256 = {Fingerprint::Type::SHA256, QByteArray::fromHex(match.captured(2).remove(":").toLatin1())};
const bool isClient = m_coreProcess.mode() == CoreMode::Client; const bool isClient = m_coreProcess.mode() == CoreMode::Client;
if ((isClient && m_checkedServers.contains(sha256Text)) || (!isClient && m_checkedClients.contains(sha256Text))) { if ((isClient && m_checkedServers.contains(sha256Text)) || (!isClient && m_checkedClients.contains(sha256Text))) {
qDebug("ignoring fingerprint, already handled"); qDebug("ignoring fingerprint, already handled");
return; return;
@ -798,7 +804,7 @@ void MainWindow::checkFingerprint(const QString &line)
auto dialogMode = isClient ? FingerprintDialogMode::Client : FingerprintDialogMode::Server; auto dialogMode = isClient ? FingerprintDialogMode::Client : FingerprintDialogMode::Server;
FingerprintDialog fingerprintDialog(this, {sha1, sha256}, dialogMode); FingerprintDialog fingerprintDialog(this, sha256, dialogMode);
connect(&fingerprintDialog, &FingerprintDialog::requestLocalPrintsDialog, this, &MainWindow::showMyFingerprint); connect(&fingerprintDialog, &FingerprintDialog::requestLocalPrintsDialog, this, &MainWindow::showMyFingerprint);
if (fingerprintDialog.exec() == QDialog::Accepted) { if (fingerprintDialog.exec() == QDialog::Accepted) {

View file

@ -13,13 +13,11 @@
#include <QPushButton> #include <QPushButton>
#include <QVBoxLayout> #include <QVBoxLayout>
FingerprintDialog::FingerprintDialog( FingerprintDialog::FingerprintDialog(QWidget *parent, const Fingerprint &fingerprint, FingerprintDialogMode mode)
QWidget *parent, const QList<Fingerprint> &fingerprints, FingerprintDialogMode mode
)
: QDialog(parent), : QDialog(parent),
m_lblHeader{new QLabel(this)}, m_lblHeader{new QLabel(this)},
m_lblFooter{new QLabel(this)}, m_lblFooter{new QLabel(this)},
m_fingerprintPreview{new FingerprintPreview(this, fingerprints)}, m_fingerprintPreview{new FingerprintPreview(this, fingerprint)},
m_buttonBox{new QDialogButtonBox(this)} m_buttonBox{new QDialogButtonBox(this)}
{ {
setWindowIcon(QIcon::fromTheme("fingerprint")); setWindowIcon(QIcon::fromTheme("fingerprint"));

View file

@ -27,7 +27,7 @@ class FingerprintDialog : public QDialog
public: public:
explicit FingerprintDialog( explicit FingerprintDialog(
QWidget *parent = nullptr, const QList<Fingerprint> &fingerprints = {}, QWidget *parent = nullptr, const Fingerprint &fingerprint = {},
FingerprintDialogMode mode = FingerprintDialogMode::Local FingerprintDialogMode mode = FingerprintDialogMode::Local
); );
~FingerprintDialog() override = default; ~FingerprintDialog() override = default;

View file

@ -52,18 +52,9 @@ bool TlsCertificate::generateFingerprint(const QString &certificateFilename)
{ {
qDebug("generating tls fingerprint"); qDebug("generating tls fingerprint");
const std::string certPath = certificateFilename.toStdString(); const std::string certPath = certificateFilename.toStdString();
try { FingerprintDatabase db;
FingerprintDatabase db; db.addTrusted(deskflow::pemFileCertFingerprint(certPath, Fingerprint::Type::SHA256));
db.addTrusted(deskflow::pemFileCertFingerprint(certPath, Fingerprint::Type::SHA1)); return db.write(Settings::tlsLocalDb());
db.addTrusted(deskflow::pemFileCertFingerprint(certPath, Fingerprint::Type::SHA256));
db.write(Settings::tlsLocalDb());
qDebug("tls fingerprint generated");
return true;
} catch (const std::exception &e) {
qCritical() << "failed to find tls fingerprint: " << e.what();
return false;
}
} }
int TlsCertificate::getCertKeyLength(const QString &path) int TlsCertificate::getCertKeyLength(const QString &path)

View file

@ -12,57 +12,36 @@
#include <net/SecureUtils.h> #include <net/SecureUtils.h>
FingerprintPreview::FingerprintPreview(QWidget *parent, const QList<Fingerprint> &fingerprints) : QFrame(parent) FingerprintPreview::FingerprintPreview(QWidget *parent, const Fingerprint &fingerprint) : QFrame(parent)
{ {
setFrameShape(QFrame::StyledPanel); setFrameShape(QFrame::StyledPanel);
setFrameStyle(QFrame::Sunken); setFrameStyle(QFrame::Sunken);
setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
QString sha1String; setLayout(fingerprint.type == Fingerprint::Type::SHA256 ? sha256Layout(fingerprint) : emptyLayout());
QString sha256String;
QString sha256Art;
for (const auto &fingerprint : fingerprints) { adjustSize();
switch (fingerprint.type) { setFixedSize(size());
case Fingerprint::Type::SHA1: }
sha1String = deskflow::formatSSLFingerprint(fingerprint.data);
break;
case Fingerprint::Type::SHA256: QLayout *FingerprintPreview::emptyLayout()
sha256String = deskflow::formatSSLFingerprintColumns(fingerprint.data); {
sha256Art = deskflow::generateFingerprintArt(fingerprint.data); auto *label = new QLabel(tr("Invalid hash format"));
break; auto *layout = new QHBoxLayout();
default: layout->addWidget(label);
qWarning() << "unknown fingerprint type:" << fingerprint.type; return layout;
break; }
}
}
auto labelSha1 = new QLabel(QStringLiteral("SHA1:"), this);
labelSha1->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
auto lblSha1 = new QLabel(sha1String, this);
lblSha1->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
lblSha1->setTextInteractionFlags(Qt::TextSelectableByMouse);
auto sha1Layout = new QHBoxLayout();
sha1Layout->addWidget(labelSha1);
sha1Layout->addWidget(lblSha1);
auto frameSha1 = new QFrame(this);
frameSha1->setFrameShape(QFrame::StyledPanel);
frameSha1->setFrameStyle(QFrame::Sunken);
frameSha1->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
frameSha1->setLayout(sha1Layout);
QLayout *FingerprintPreview::sha256Layout(const Fingerprint &fingerprint)
{
auto labelSha256 = new QLabel(QStringLiteral("SHA256:"), this); auto labelSha256 = new QLabel(QStringLiteral("SHA256:"), this);
labelSha256->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); labelSha256->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
auto lblSha256String = new QLabel(sha256String, this); auto lblSha256String = new QLabel(deskflow::formatSSLFingerprintColumns(fingerprint.data), this);
lblSha256String->setAlignment(Qt::AlignTop | Qt::AlignHCenter); lblSha256String->setAlignment(Qt::AlignTop | Qt::AlignHCenter);
lblSha256String->setTextInteractionFlags(Qt::TextSelectableByMouse); lblSha256String->setTextInteractionFlags(Qt::TextSelectableByMouse);
auto lblSha256Art = new QLabel(sha256Art, this); auto lblSha256Art = new QLabel(deskflow::generateFingerprintArt(fingerprint.data), this);
lblSha256Art->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter); lblSha256Art->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
lblSha256Art->setTextInteractionFlags(Qt::TextSelectableByMouse); lblSha256Art->setTextInteractionFlags(Qt::TextSelectableByMouse);
@ -87,19 +66,7 @@ FingerprintPreview::FingerprintPreview(QWidget *parent, const QList<Fingerprint>
frameSha256->setLayout(sha256Layout); frameSha256->setLayout(sha256Layout);
auto layout = new QVBoxLayout(); auto layout = new QVBoxLayout();
layout->addWidget(frameSha1);
layout->addWidget(frameSha256); layout->addWidget(frameSha256);
setLayout(layout); return layout;
if (sha1String.isEmpty()) {
frameSha1->setVisible(false);
}
if (sha256String.isEmpty()) {
frameSha256->setVisible(false);
}
adjustSize();
setFixedSize(size());
} }

View file

@ -13,6 +13,10 @@ class FingerprintPreview : public QFrame
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit FingerprintPreview(QWidget *parent, const QList<Fingerprint> &fingerprints = {}); explicit FingerprintPreview(QWidget *parent, const Fingerprint &fingerprint = {});
~FingerprintPreview() override = default; ~FingerprintPreview() override = default;
private:
QLayout *emptyLayout();
QLayout *sha256Layout(const Fingerprint &fingerprint = {});
}; };

View file

@ -48,29 +48,30 @@ void FingerprintDatabase::readStream(QTextStream &in)
} }
} }
void FingerprintDatabase::write(const QString &path) bool FingerprintDatabase::write(const QString &path)
{ {
QFile file(path); QFile file(path);
if (!file.open(QIODevice::WriteOnly)) if (!file.open(QIODevice::WriteOnly))
return; return false;
QTextStream out(&file); QTextStream out(&file);
writeStream(out); return (writeStream(out));
} }
void FingerprintDatabase::writeStream(QTextStream &out) bool FingerprintDatabase::writeStream(QTextStream &out)
{ {
// Make sure the stream has somewhere to write // Make sure the stream has somewhere to write
if (!out.device() && !out.string()) if (!out.device() && !out.string())
return; return false;
if (out.device()) { if (out.device()) {
if (!out.device()->isWritable()) if (!out.device()->isWritable())
return; return false;
} }
for (const auto &fingerprint : std::as_const(m_fingerprints)) { for (const auto &fingerprint : std::as_const(m_fingerprints)) {
out << fingerprint.toDbLine() << "\n"; out << fingerprint.toDbLine() << "\n";
} }
return true;
} }
void FingerprintDatabase::clear() void FingerprintDatabase::clear()

View file

@ -15,10 +15,10 @@ class FingerprintDatabase
{ {
public: public:
void read(const QString &path); void read(const QString &path);
void write(const QString &path); bool write(const QString &path);
void readStream(QTextStream &in); void readStream(QTextStream &in);
void writeStream(QTextStream &out); bool writeStream(QTextStream &out);
void clear(); void clear();
void addTrusted(const Fingerprint &fingerprint); void addTrusted(const Fingerprint &fingerprint);

View file

@ -645,23 +645,14 @@ void SecureSocket::disconnect()
bool SecureSocket::verifyCertFingerprint(const QString &FingerprintDatabasePath) bool SecureSocket::verifyCertFingerprint(const QString &FingerprintDatabasePath)
{ {
Fingerprint sha1; const auto cert = SSL_get_peer_certificate(m_ssl->m_ssl);
Fingerprint sha256; const auto sha256 = deskflow::sslCertFingerprint(cert, Fingerprint::Type::SHA256);
try {
auto cert = SSL_get_peer_certificate(m_ssl->m_ssl);
sha1 = deskflow::sslCertFingerprint(cert, Fingerprint::Type::SHA1);
sha256 = deskflow::sslCertFingerprint(cert, Fingerprint::Type::SHA256);
} catch (const std::exception &e) {
LOG((CLOG_ERR "%s", e.what()));
return false;
}
// Gui Must Parse these two lines, DO NOT CHANGE if (!sha256.isValid())
LOG( return false;
(CLOG_NOTE "peer fingerprint: (SHA1) %s (SHA256) %s",
deskflow::formatSSLFingerprint(sha1.data).toStdString().c_str(), // Gui Must Parse this line, DO NOT CHANGE
deskflow::formatSSLFingerprint(sha256.data).toStdString().c_str()) LOG((CLOG_NOTE "peer fingerprint: %s", deskflow::formatSSLFingerprint(sha256.data, false).toStdString().c_str()));
);
QFile file(FingerprintDatabasePath); QFile file(FingerprintDatabasePath);