refactor: do not write sha1 to localdb and no longer send sha1 as part of comparison
This commit is contained in:
parent
63e87c16d1
commit
332e6c4a4d
10 changed files with 63 additions and 106 deletions
|
|
@ -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";
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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"));
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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());
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 = {});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue