Merge pull request #1346 from p12tic/client-identity-verification
Implement client identity verification [SECURITY VULNERABILITIES CVE-2021-42072, CVE-2021-42073]
This commit is contained in:
commit
b5adc93e2b
|
@ -0,0 +1,7 @@
|
||||||
|
SECURITY ISSUE
|
||||||
|
|
||||||
|
Barrier now supports client identity verification (fixes CVE-2021-42072, CVE-2021-42073).
|
||||||
|
|
||||||
|
To support seamless upgrades from older versions of Barrier this is currently disabled by default.
|
||||||
|
The feature can be enabled in the settings dialog. If enabled, older clients of Barrier will be
|
||||||
|
rejected.
|
|
@ -0,0 +1 @@
|
||||||
|
Barrier client now sends certificate that the server can verify.
|
|
@ -29,6 +29,7 @@ set(GUI_SOURCE_FILES
|
||||||
src/CommandProcess.cpp
|
src/CommandProcess.cpp
|
||||||
src/DataDownloader.cpp
|
src/DataDownloader.cpp
|
||||||
src/DisplayIsValid.cpp
|
src/DisplayIsValid.cpp
|
||||||
|
src/FingerprintAcceptDialog.cpp
|
||||||
src/HotkeyDialog.cpp
|
src/HotkeyDialog.cpp
|
||||||
src/IpcClient.cpp
|
src/IpcClient.cpp
|
||||||
src/Ipc.cpp
|
src/Ipc.cpp
|
||||||
|
@ -104,6 +105,7 @@ set(GUI_UI_FILES
|
||||||
src/AboutDialogBase.ui
|
src/AboutDialogBase.ui
|
||||||
src/ActionDialogBase.ui
|
src/ActionDialogBase.ui
|
||||||
src/AddClientDialogBase.ui
|
src/AddClientDialogBase.ui
|
||||||
|
src/FingerprintAcceptDialog.ui
|
||||||
src/HotkeyDialogBase.ui
|
src/HotkeyDialogBase.ui
|
||||||
src/LogWindowBase.ui
|
src/LogWindowBase.ui
|
||||||
src/MainWindowBase.ui
|
src/MainWindowBase.ui
|
||||||
|
|
|
@ -158,6 +158,8 @@ void AppConfig::loadSettings()
|
||||||
m_ElevateMode = static_cast<ElevateMode>(elevateMode.toInt());
|
m_ElevateMode = static_cast<ElevateMode>(elevateMode.toInt());
|
||||||
m_AutoConfigPrompted = settings().value("autoConfigPrompted", false).toBool();
|
m_AutoConfigPrompted = settings().value("autoConfigPrompted", false).toBool();
|
||||||
m_CryptoEnabled = settings().value("cryptoEnabled", true).toBool();
|
m_CryptoEnabled = settings().value("cryptoEnabled", true).toBool();
|
||||||
|
// TODO: set default value of requireClientCertificate to true on Barrier 2.5.0
|
||||||
|
m_RequireClientCertificate = settings().value("requireClientCertificate", false).toBool();
|
||||||
m_AutoHide = settings().value("autoHide", false).toBool();
|
m_AutoHide = settings().value("autoHide", false).toBool();
|
||||||
m_AutoStart = settings().value("autoStart", false).toBool();
|
m_AutoStart = settings().value("autoStart", false).toBool();
|
||||||
m_MinimizeToTray = settings().value("minimizeToTray", false).toBool();
|
m_MinimizeToTray = settings().value("minimizeToTray", false).toBool();
|
||||||
|
@ -181,6 +183,7 @@ void AppConfig::saveSettings()
|
||||||
settings().setValue("elevateModeEnum", static_cast<int>(m_ElevateMode));
|
settings().setValue("elevateModeEnum", static_cast<int>(m_ElevateMode));
|
||||||
settings().setValue("autoConfigPrompted", m_AutoConfigPrompted);
|
settings().setValue("autoConfigPrompted", m_AutoConfigPrompted);
|
||||||
settings().setValue("cryptoEnabled", m_CryptoEnabled);
|
settings().setValue("cryptoEnabled", m_CryptoEnabled);
|
||||||
|
settings().setValue("requireClientCertificate", m_RequireClientCertificate);
|
||||||
settings().setValue("autoHide", m_AutoHide);
|
settings().setValue("autoHide", m_AutoHide);
|
||||||
settings().setValue("autoStart", m_AutoStart);
|
settings().setValue("autoStart", m_AutoStart);
|
||||||
settings().setValue("minimizeToTray", m_MinimizeToTray);
|
settings().setValue("minimizeToTray", m_MinimizeToTray);
|
||||||
|
@ -225,6 +228,10 @@ void AppConfig::setCryptoEnabled(bool e) { m_CryptoEnabled = e; }
|
||||||
|
|
||||||
bool AppConfig::getCryptoEnabled() const { return m_CryptoEnabled; }
|
bool AppConfig::getCryptoEnabled() const { return m_CryptoEnabled; }
|
||||||
|
|
||||||
|
void AppConfig::setRequireClientCertificate(bool e) { m_RequireClientCertificate = e; }
|
||||||
|
|
||||||
|
bool AppConfig::getRequireClientCertificate() const { return m_RequireClientCertificate; }
|
||||||
|
|
||||||
void AppConfig::setAutoHide(bool b) { m_AutoHide = b; }
|
void AppConfig::setAutoHide(bool b) { m_AutoHide = b; }
|
||||||
|
|
||||||
bool AppConfig::getAutoHide() { return m_AutoHide; }
|
bool AppConfig::getAutoHide() { return m_AutoHide; }
|
||||||
|
|
|
@ -91,6 +91,9 @@ class AppConfig: public QObject
|
||||||
void setCryptoEnabled(bool e);
|
void setCryptoEnabled(bool e);
|
||||||
bool getCryptoEnabled() const;
|
bool getCryptoEnabled() const;
|
||||||
|
|
||||||
|
void setRequireClientCertificate(bool e);
|
||||||
|
bool getRequireClientCertificate() const;
|
||||||
|
|
||||||
void setAutoHide(bool b);
|
void setAutoHide(bool b);
|
||||||
bool getAutoHide();
|
bool getAutoHide();
|
||||||
|
|
||||||
|
@ -132,6 +135,7 @@ protected:
|
||||||
ElevateMode m_ElevateMode;
|
ElevateMode m_ElevateMode;
|
||||||
bool m_AutoConfigPrompted;
|
bool m_AutoConfigPrompted;
|
||||||
bool m_CryptoEnabled;
|
bool m_CryptoEnabled;
|
||||||
|
bool m_RequireClientCertificate = false;
|
||||||
bool m_AutoHide;
|
bool m_AutoHide;
|
||||||
bool m_AutoStart;
|
bool m_AutoStart;
|
||||||
bool m_MinimizeToTray;
|
bool m_MinimizeToTray;
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
barrier -- mouse and keyboard sharing utility
|
||||||
|
Copyright (C) Barrier contributors
|
||||||
|
|
||||||
|
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 "FingerprintAcceptDialog.h"
|
||||||
|
#include "ui_FingerprintAcceptDialog.h"
|
||||||
|
#include "net/SecureUtils.h"
|
||||||
|
|
||||||
|
FingerprintAcceptDialog::FingerprintAcceptDialog(QWidget *parent,
|
||||||
|
BarrierType type,
|
||||||
|
const barrier::FingerprintData& fingerprint_sha1,
|
||||||
|
const barrier::FingerprintData& fingerprint_sha256) :
|
||||||
|
QDialog(parent),
|
||||||
|
ui_{std::make_unique<Ui::FingerprintAcceptDialog>()}
|
||||||
|
{
|
||||||
|
ui_->setupUi(this);
|
||||||
|
|
||||||
|
if (type == BarrierType::Server) {
|
||||||
|
ui_->label_sha1->hide();
|
||||||
|
ui_->label_sha1_fingerprint_full->hide();
|
||||||
|
} else {
|
||||||
|
ui_->label_sha1_fingerprint_full->setText(
|
||||||
|
QString::fromStdString(barrier::format_ssl_fingerprint(fingerprint_sha1.data)));
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_->label_sha256_fingerprint_full->setText(
|
||||||
|
QString::fromStdString(barrier::format_ssl_fingerprint_columns(fingerprint_sha256.data)));
|
||||||
|
ui_->label_sha256_fingerprint_randomart->setText(
|
||||||
|
QString::fromStdString(barrier::create_fingerprint_randomart(fingerprint_sha256.data)));
|
||||||
|
|
||||||
|
QString explanation;
|
||||||
|
if (type == BarrierType::Server) {
|
||||||
|
explanation = tr("This is a client fingerprint. You should compare this "
|
||||||
|
"fingerprint to the one on your client's screen. If the "
|
||||||
|
"two don't match exactly, then it's probably not the client "
|
||||||
|
"you're expecting (it could be a malicious user).\n\n"
|
||||||
|
"To automatically trust this fingerprint for future "
|
||||||
|
"connections, click Yes. To reject this fingerprint and "
|
||||||
|
"disconnect the client, click No.");
|
||||||
|
} else {
|
||||||
|
explanation = tr("This is a server fingerprint. You should compare this "
|
||||||
|
"fingerprint to the one on your server's screen. If the "
|
||||||
|
"two don't match exactly, then it's probably not the server "
|
||||||
|
"you're expecting (it could be a malicious user).\n\n"
|
||||||
|
"To automatically trust this fingerprint for future "
|
||||||
|
"connections, click Yes. To reject this fingerprint and "
|
||||||
|
"disconnect from the server, click No.");
|
||||||
|
}
|
||||||
|
ui_->label_explanation->setText(explanation);
|
||||||
|
}
|
||||||
|
|
||||||
|
FingerprintAcceptDialog::~FingerprintAcceptDialog() = default;
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
barrier -- mouse and keyboard sharing utility
|
||||||
|
Copyright (C) Barrier contributors
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BARRIER_GUI_FINGERPRINT_ACCEPT_DIALOG_H
|
||||||
|
#define BARRIER_GUI_FINGERPRINT_ACCEPT_DIALOG_H
|
||||||
|
|
||||||
|
#include "net/FingerprintData.h"
|
||||||
|
#include "barrier/BarrierType.h"
|
||||||
|
#include <QDialog>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class FingerprintAcceptDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class FingerprintAcceptDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit FingerprintAcceptDialog(QWidget* parent,
|
||||||
|
BarrierType type,
|
||||||
|
const barrier::FingerprintData& fingerprint_sha1,
|
||||||
|
const barrier::FingerprintData& fingerprint_sha256);
|
||||||
|
~FingerprintAcceptDialog() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Ui::FingerprintAcceptDialog> ui_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BARRIER_GUI_FINGERPRINT_ACCEPT_DIALOG_H
|
|
@ -0,0 +1,174 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>FingerprintAcceptDialog</class>
|
||||||
|
<widget class="QDialog" name="FingerprintAcceptDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>600</width>
|
||||||
|
<height>400</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Ignored" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Security question</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SetFixedSize</enum>
|
||||||
|
</property>
|
||||||
|
<item row="6" column="0" colspan="2">
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::No|QDialogButtonBox::Yes</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0" colspan="2">
|
||||||
|
<widget class="QLabel" name="label_sha1">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>SHA1 (deprecated, compare to old servers only)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0" colspan="2">
|
||||||
|
<widget class="QLabel" name="label_explanation">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="margin">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0" colspan="2">
|
||||||
|
<widget class="QLabel" name="label_sha1_fingerprint_full">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0" colspan="2">
|
||||||
|
<widget class="QLabel" name="label_title">
|
||||||
|
<property name="text">
|
||||||
|
<string>Do you trust this fingerprint?</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLabel" name="label_sha256_fingerprint_randomart">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Courier</family>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_sha256_fingerprint_full">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0" colspan="2">
|
||||||
|
<widget class="QLabel" name="label_sha256">
|
||||||
|
<property name="text">
|
||||||
|
<string>SHA256:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>FingerprintAcceptDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>FingerprintAcceptDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>260</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
|
@ -26,6 +26,7 @@
|
||||||
#include "ZeroconfService.h"
|
#include "ZeroconfService.h"
|
||||||
#include "DataDownloader.h"
|
#include "DataDownloader.h"
|
||||||
#include "CommandProcess.h"
|
#include "CommandProcess.h"
|
||||||
|
#include "FingerprintAcceptDialog.h"
|
||||||
#include "QUtility.h"
|
#include "QUtility.h"
|
||||||
#include "ProcessorArch.h"
|
#include "ProcessorArch.h"
|
||||||
#include "SslCertificate.h"
|
#include "SslCertificate.h"
|
||||||
|
@ -427,7 +428,7 @@ void MainWindow::checkConnected(const QString& line)
|
||||||
|
|
||||||
void MainWindow::checkFingerprint(const QString& line)
|
void MainWindow::checkFingerprint(const QString& line)
|
||||||
{
|
{
|
||||||
QRegExp fingerprintRegex(".*server fingerprint \\(SHA1\\): ([A-F0-9:]+) \\(SHA256\\): ([A-F0-9:]+)");
|
QRegExp fingerprintRegex(".*peer fingerprint \\(SHA1\\): ([A-F0-9:]+) \\(SHA256\\): ([A-F0-9:]+)");
|
||||||
if (!fingerprintRegex.exactMatch(line)) {
|
if (!fingerprintRegex.exactMatch(line)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -442,7 +443,16 @@ void MainWindow::checkFingerprint(const QString& line)
|
||||||
barrier::string::from_hex(fingerprintRegex.cap(2).toStdString())
|
barrier::string::from_hex(fingerprintRegex.cap(2).toStdString())
|
||||||
};
|
};
|
||||||
|
|
||||||
auto db_path = barrier::DataDirectories::trusted_servers_ssl_fingerprints_path();
|
bool is_client = barrier_type() == BarrierType::Client;
|
||||||
|
|
||||||
|
auto db_path = is_client
|
||||||
|
? barrier::DataDirectories::trusted_servers_ssl_fingerprints_path()
|
||||||
|
: barrier::DataDirectories::trusted_clients_ssl_fingerprints_path();
|
||||||
|
|
||||||
|
auto db_dir = db_path.parent_path();
|
||||||
|
if (!barrier::fs::exists(db_dir)) {
|
||||||
|
barrier::fs::create_directories(db_dir);
|
||||||
|
}
|
||||||
|
|
||||||
// We compare only SHA256 fingerprints, but show both SHA1 and SHA256 so that the users can
|
// We compare only SHA256 fingerprints, but show both SHA1 and SHA256 so that the users can
|
||||||
// still verify fingerprints on old Barrier servers. This way the only time when we are exposed
|
// still verify fingerprints on old Barrier servers. This way the only time when we are exposed
|
||||||
|
@ -456,37 +466,20 @@ void MainWindow::checkFingerprint(const QString& line)
|
||||||
static bool messageBoxAlreadyShown = false;
|
static bool messageBoxAlreadyShown = false;
|
||||||
|
|
||||||
if (!messageBoxAlreadyShown) {
|
if (!messageBoxAlreadyShown) {
|
||||||
|
if (is_client) {
|
||||||
stopBarrier();
|
stopBarrier();
|
||||||
|
}
|
||||||
|
|
||||||
messageBoxAlreadyShown = true;
|
messageBoxAlreadyShown = true;
|
||||||
QMessageBox::StandardButton fingerprintReply =
|
FingerprintAcceptDialog dialog{this, barrier_type(), fingerprint_sha1, fingerprint_sha256};
|
||||||
QMessageBox::information(
|
if (dialog.exec() == QDialog::Accepted) {
|
||||||
this, tr("Security question"),
|
|
||||||
tr("Do you trust this fingerprint?\n\n"
|
|
||||||
"SHA256:\n"
|
|
||||||
"%1\n"
|
|
||||||
"%2\n\n"
|
|
||||||
"SHA1 (obsolete, when using old Barrier server):\n"
|
|
||||||
"%3\n\n"
|
|
||||||
"This is a server fingerprint. You should compare this "
|
|
||||||
"fingerprint to the one on your server's screen. If the "
|
|
||||||
"two don't match exactly, then it's probably not the server "
|
|
||||||
"you're expecting (it could be a malicious user).\n\n"
|
|
||||||
"To automatically trust this fingerprint for future "
|
|
||||||
"connections, click Yes. To reject this fingerprint and "
|
|
||||||
"disconnect from the server, click No.")
|
|
||||||
.arg(QString::fromStdString(barrier::format_ssl_fingerprint(fingerprint_sha256.data)))
|
|
||||||
.arg(QString::fromStdString(
|
|
||||||
barrier::create_fingerprint_randomart(fingerprint_sha256.data)))
|
|
||||||
.arg(QString::fromStdString(barrier::format_ssl_fingerprint(fingerprint_sha1.data))),
|
|
||||||
QMessageBox::Yes | QMessageBox::No);
|
|
||||||
|
|
||||||
if (fingerprintReply == QMessageBox::Yes) {
|
|
||||||
// restart core process after trusting fingerprint.
|
// restart core process after trusting fingerprint.
|
||||||
db.add_trusted(fingerprint_sha256);
|
db.add_trusted(fingerprint_sha256);
|
||||||
db.write(db_path);
|
db.write(db_path);
|
||||||
|
if (is_client) {
|
||||||
startBarrier();
|
startBarrier();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
messageBoxAlreadyShown = false;
|
messageBoxAlreadyShown = false;
|
||||||
}
|
}
|
||||||
|
@ -567,8 +560,8 @@ void MainWindow::startBarrier()
|
||||||
args << "--profile-dir" << QString::fromStdString("\"" + barrier::DataDirectories::profile().u8string() + "\"");
|
args << "--profile-dir" << QString::fromStdString("\"" + barrier::DataDirectories::profile().u8string() + "\"");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((barrierType() == barrierClient && !clientArgs(args, app))
|
if ((barrier_type() == BarrierType::Client && !clientArgs(args, app))
|
||||||
|| (barrierType() == barrierServer && !serverArgs(args, app)))
|
|| (barrier_type() == BarrierType::Server && !serverArgs(args, app)))
|
||||||
{
|
{
|
||||||
stopBarrier();
|
stopBarrier();
|
||||||
return;
|
return;
|
||||||
|
@ -583,7 +576,7 @@ void MainWindow::startBarrier()
|
||||||
|
|
||||||
m_pLogWindow->startNewInstance();
|
m_pLogWindow->startNewInstance();
|
||||||
|
|
||||||
appendLogInfo("starting " + QString(barrierType() == barrierServer ? "server" : "client"));
|
appendLogInfo("starting " + QString(barrier_type() == BarrierType::Server ? "server" : "client"));
|
||||||
|
|
||||||
qDebug() << args;
|
qDebug() << args;
|
||||||
|
|
||||||
|
@ -693,6 +686,11 @@ QString MainWindow::configFilename()
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BarrierType MainWindow::barrier_type() const
|
||||||
|
{
|
||||||
|
return m_pGroupClient->isChecked() ? BarrierType::Client : BarrierType::Server;
|
||||||
|
}
|
||||||
|
|
||||||
QString MainWindow::address()
|
QString MainWindow::address()
|
||||||
{
|
{
|
||||||
QString address = appConfig().networkInterface();
|
QString address = appConfig().networkInterface();
|
||||||
|
@ -729,6 +727,10 @@ bool MainWindow::serverArgs(QStringList& args, QString& app)
|
||||||
args << "--log" << appConfig().logFilenameCmd();
|
args << "--log" << appConfig().logFilenameCmd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!appConfig().getRequireClientCertificate()) {
|
||||||
|
args << "--disable-client-cert-checking";
|
||||||
|
}
|
||||||
|
|
||||||
QString configFilename = this->configFilename();
|
QString configFilename = this->configFilename();
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
// wrap in quotes in case username contains spaces.
|
// wrap in quotes in case username contains spaces.
|
||||||
|
@ -983,7 +985,7 @@ void MainWindow::updateZeroconfService()
|
||||||
m_pZeroconfService = NULL;
|
m_pZeroconfService = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_AppConfig->autoConfig() || barrierType() == barrierServer) {
|
if (m_AppConfig->autoConfig() || barrier_type() == BarrierType::Server) {
|
||||||
m_pZeroconfService = new ZeroconfService(this);
|
m_pZeroconfService = new ZeroconfService(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
|
|
||||||
#define MAINWINDOW__H
|
#define MAINWINDOW__H
|
||||||
|
|
||||||
|
#include "barrier/BarrierType.h"
|
||||||
|
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QSystemTrayIcon>
|
#include <QSystemTrayIcon>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
@ -76,12 +78,6 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
|
||||||
barrierTransfering
|
barrierTransfering
|
||||||
};
|
};
|
||||||
|
|
||||||
enum qBarrierType
|
|
||||||
{
|
|
||||||
barrierClient,
|
|
||||||
barrierServer
|
|
||||||
};
|
|
||||||
|
|
||||||
enum qLevel {
|
enum qLevel {
|
||||||
Error,
|
Error,
|
||||||
Info
|
Info
|
||||||
|
@ -98,7 +94,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void setVisible(bool visible);
|
void setVisible(bool visible);
|
||||||
int barrierType() const { return m_pGroupClient->isChecked() ? barrierClient : barrierServer; }
|
BarrierType barrier_type() const;
|
||||||
int barrierState() const { return m_BarrierState; }
|
int barrierState() const { return m_BarrierState; }
|
||||||
QString hostname() const { return m_pLineEditHostname->text(); }
|
QString hostname() const { return m_pLineEditHostname->text(); }
|
||||||
QString configFilename();
|
QString configFilename();
|
||||||
|
|
|
@ -55,107 +55,6 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="m_pLabelFingerprint">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>SSL Fingerprint:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="m_pLabelLocalFingerprint">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="textFormat">
|
|
||||||
<enum>Qt::PlainText</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QToolButton" name="toolbutton_show_fingerprint">
|
|
||||||
<property name="text">
|
|
||||||
<string>...</string>
|
|
||||||
</property>
|
|
||||||
<property name="arrowType">
|
|
||||||
<enum>Qt::DownArrow</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QFrame" name="frame_fingerprint_details">
|
|
||||||
<property name="frameShape">
|
|
||||||
<enum>QFrame::StyledPanel</enum>
|
|
||||||
</property>
|
|
||||||
<property name="frameShadow">
|
|
||||||
<enum>QFrame::Raised</enum>
|
|
||||||
</property>
|
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
|
||||||
<property name="sizeConstraint">
|
|
||||||
<enum>QLayout::SetMinimumSize</enum>
|
|
||||||
</property>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QLabel" name="label_sha256_randomart">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Courier</family>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="textInteractionFlags">
|
|
||||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0" colspan="2">
|
|
||||||
<widget class="QLabel" name="label_sha1">
|
|
||||||
<property name="text">
|
|
||||||
<string>SHA1 (deprecated, compare to old clients only):</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0" colspan="2">
|
|
||||||
<widget class="QLabel" name="label_sha1_fingerprint_full">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="textInteractionFlags">
|
|
||||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0" colspan="2">
|
|
||||||
<widget class="QLabel" name="label_sha256">
|
|
||||||
<property name="text">
|
|
||||||
<string>SHA256:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_sha256_fingerprint_full">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="textInteractionFlags">
|
|
||||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QRadioButton" name="m_pRadioInternalConfig">
|
<widget class="QRadioButton" name="m_pRadioInternalConfig">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -305,6 +204,107 @@
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="m_pLabelFingerprint">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>SSL Fingerprint:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="m_pLabelLocalFingerprint">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="textFormat">
|
||||||
|
<enum>Qt::PlainText</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="toolbutton_show_fingerprint">
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
<property name="arrowType">
|
||||||
|
<enum>Qt::DownArrow</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QFrame" name="frame_fingerprint_details">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::StyledPanel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Raised</enum>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SetMinimumSize</enum>
|
||||||
|
</property>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLabel" name="label_sha256_randomart">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Courier</family>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0" colspan="2">
|
||||||
|
<widget class="QLabel" name="label_sha1">
|
||||||
|
<property name="text">
|
||||||
|
<string>SHA1 (deprecated, compare to old clients and servers only):</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0" colspan="2">
|
||||||
|
<widget class="QLabel" name="label_sha1_fingerprint_full">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0" colspan="2">
|
||||||
|
<widget class="QLabel" name="label_sha256">
|
||||||
|
<property name="text">
|
||||||
|
<string>SHA256:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_sha256_fingerprint_full">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<property name="sizeConstraint">
|
<property name="sizeConstraint">
|
||||||
|
|
|
@ -51,6 +51,7 @@ SettingsDialog::SettingsDialog(QWidget* parent, AppConfig& config) :
|
||||||
m_pCheckBoxAutoStart->setChecked(appConfig().getAutoStart());
|
m_pCheckBoxAutoStart->setChecked(appConfig().getAutoStart());
|
||||||
m_pCheckBoxMinimizeToTray->setChecked(appConfig().getMinimizeToTray());
|
m_pCheckBoxMinimizeToTray->setChecked(appConfig().getMinimizeToTray());
|
||||||
m_pCheckBoxEnableCrypto->setChecked(m_appConfig.getCryptoEnabled());
|
m_pCheckBoxEnableCrypto->setChecked(m_appConfig.getCryptoEnabled());
|
||||||
|
checkbox_require_client_certificate->setChecked(m_appConfig.getRequireClientCertificate());
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
m_pComboElevate->setCurrentIndex(static_cast<int>(appConfig().elevateMode()));
|
m_pComboElevate->setCurrentIndex(static_cast<int>(appConfig().elevateMode()));
|
||||||
|
@ -67,6 +68,7 @@ void SettingsDialog::accept()
|
||||||
m_appConfig.setPort(m_pSpinBoxPort->value());
|
m_appConfig.setPort(m_pSpinBoxPort->value());
|
||||||
m_appConfig.setNetworkInterface(m_pLineEditInterface->text());
|
m_appConfig.setNetworkInterface(m_pLineEditInterface->text());
|
||||||
m_appConfig.setCryptoEnabled(m_pCheckBoxEnableCrypto->isChecked());
|
m_appConfig.setCryptoEnabled(m_pCheckBoxEnableCrypto->isChecked());
|
||||||
|
m_appConfig.setRequireClientCertificate(checkbox_require_client_certificate->isChecked());
|
||||||
m_appConfig.setLogLevel(m_pComboLogLevel->currentIndex());
|
m_appConfig.setLogLevel(m_pComboLogLevel->currentIndex());
|
||||||
m_appConfig.setLogToFile(m_pCheckBoxLogToFile->isChecked());
|
m_appConfig.setLogToFile(m_pCheckBoxLogToFile->isChecked());
|
||||||
m_appConfig.setLogFilename(m_pLineEditLogFilename->text());
|
m_appConfig.setLogFilename(m_pLineEditLogFilename->text());
|
||||||
|
|
|
@ -142,6 +142,16 @@
|
||||||
<string>Networking</string>
|
<string>Networking</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_3">
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="m_pLabel_21">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Address:</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>m_pLineEditInterface</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="m_pLabel_20">
|
<widget class="QLabel" name="m_pLabel_20">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -171,16 +181,6 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="m_pLabel_21">
|
|
||||||
<property name="text">
|
|
||||||
<string>&Address:</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>m_pLineEditInterface</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QLineEdit" name="m_pLineEditInterface">
|
<widget class="QLineEdit" name="m_pLineEditInterface">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
|
@ -188,13 +188,20 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="2" column="0" colspan="2">
|
||||||
<widget class="QCheckBox" name="m_pCheckBoxEnableCrypto">
|
<widget class="QCheckBox" name="m_pCheckBoxEnableCrypto">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Enable &SSL</string>
|
<string>Enable &SSL</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="3" column="0" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="checkbox_require_client_certificate">
|
||||||
|
<property name="text">
|
||||||
|
<string>Require client certificate</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -216,19 +223,20 @@
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
<item row="0" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="m_pLabel_3">
|
<widget class="QCheckBox" name="m_pCheckBoxLogToFile">
|
||||||
<property name="minimumSize">
|
<property name="text">
|
||||||
<size>
|
<string>Log to file:</string>
|
||||||
<width>75</width>
|
</property>
|
||||||
<height>0</height>
|
</widget>
|
||||||
</size>
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QPushButton" name="m_pButtonBrowseLog">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Logging level:</string>
|
<string>Browse...</string>
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>m_pComboLogLevel</cstring>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -271,10 +279,19 @@
|
||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QCheckBox" name="m_pCheckBoxLogToFile">
|
<widget class="QLabel" name="m_pLabel_3">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>75</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Log to file:</string>
|
<string>&Logging level:</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>m_pComboLogLevel</cstring>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -285,16 +302,6 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="2">
|
|
||||||
<widget class="QPushButton" name="m_pButtonBrowseLog">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Browse...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -65,6 +65,11 @@ void SslCertificate::generate_fingerprint(const barrier::fs::path& cert_path)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
auto local_path = barrier::DataDirectories::local_ssl_fingerprints_path();
|
auto local_path = barrier::DataDirectories::local_ssl_fingerprints_path();
|
||||||
|
auto local_dir = local_path.parent_path();
|
||||||
|
if (!barrier::fs::exists(local_dir)) {
|
||||||
|
barrier::fs::create_directories(local_dir);
|
||||||
|
}
|
||||||
|
|
||||||
barrier::FingerprintDatabase db;
|
barrier::FingerprintDatabase db;
|
||||||
db.add_trusted(barrier::get_pem_file_cert_fingerprint(cert_path.u8string(),
|
db.add_trusted(barrier::get_pem_file_cert_fingerprint(cert_path.u8string(),
|
||||||
barrier::FingerprintType::SHA1));
|
barrier::FingerprintType::SHA1));
|
||||||
|
|
|
@ -66,7 +66,7 @@ ZeroconfService::ZeroconfService(MainWindow* mainWindow) :
|
||||||
m_ServiceRegistered(false)
|
m_ServiceRegistered(false)
|
||||||
{
|
{
|
||||||
silence_avahi_warning();
|
silence_avahi_warning();
|
||||||
if (m_pMainWindow->barrierType() == MainWindow::barrierServer) {
|
if (m_pMainWindow->barrier_type() == BarrierType::Server) {
|
||||||
if (registerService(true)) {
|
if (registerService(true)) {
|
||||||
m_pZeroconfBrowser = new ZeroconfBrowser(this);
|
m_pZeroconfBrowser = new ZeroconfBrowser(this);
|
||||||
connect(m_pZeroconfBrowser, SIGNAL(
|
connect(m_pZeroconfBrowser, SIGNAL(
|
||||||
|
|
|
@ -65,7 +65,9 @@ ArgParser::parseServerArgs(ServerArgs& args, int argc, const char* const* argv)
|
||||||
// save screen change script path
|
// save screen change script path
|
||||||
args.m_screenChangeScript = argv[++i];
|
args.m_screenChangeScript = argv[++i];
|
||||||
}
|
}
|
||||||
else {
|
else if (isArg(i, argc, argv, nullptr, "--disable-client-cert-checking")) {
|
||||||
|
args.check_client_certificates = false;
|
||||||
|
} else {
|
||||||
LOG((CLOG_PRINT "%s: unrecognized option `%s'" BYE, args.m_exename.c_str(), argv[i], args.m_exename.c_str()));
|
LOG((CLOG_PRINT "%s: unrecognized option `%s'" BYE, args.m_exename.c_str(), argv[i], args.m_exename.c_str()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
barrier -- mouse and keyboard sharing utility
|
||||||
|
Copyright (C) Barrier contributors
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BARRIER_LIB_BARRIER_BARRIER_TYPE_H
|
||||||
|
#define BARRIER_LIB_BARRIER_BARRIER_TYPE_H
|
||||||
|
|
||||||
|
enum class BarrierType {
|
||||||
|
Server,
|
||||||
|
Client
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BARRIER_LIB_BARRIER_BARRIER_TYPE_H
|
|
@ -148,7 +148,10 @@ ServerApp::help()
|
||||||
<< "Options:\n"
|
<< "Options:\n"
|
||||||
<< " -a, --address <address> listen for clients on the given address.\n"
|
<< " -a, --address <address> listen for clients on the given address.\n"
|
||||||
<< " -c, --config <pathname> use the named configuration file instead.\n"
|
<< " -c, --config <pathname> use the named configuration file instead.\n"
|
||||||
<< HELP_COMMON_INFO_1 << WINAPI_INFO << HELP_SYS_INFO << HELP_COMMON_INFO_2 << "\n"
|
<< HELP_COMMON_INFO_1
|
||||||
|
<< " --disable-client-cert-checking disable client SSL certificate \n"
|
||||||
|
" checking (deprecated)\n"
|
||||||
|
<< WINAPI_INFO << HELP_SYS_INFO << HELP_COMMON_INFO_2 << "\n"
|
||||||
<< "Default options are marked with a *\n"
|
<< "Default options are marked with a *\n"
|
||||||
<< "\n"
|
<< "\n"
|
||||||
<< "The argument for --address is of the form: [<hostname>][:<port>]. The\n"
|
<< "The argument for --address is of the form: [<hostname>][:<port>]. The\n"
|
||||||
|
@ -655,11 +658,18 @@ ServerApp::handleResume(const Event&, void*)
|
||||||
ClientListener*
|
ClientListener*
|
||||||
ServerApp::openClientListener(const NetworkAddress& address)
|
ServerApp::openClientListener(const NetworkAddress& address)
|
||||||
{
|
{
|
||||||
|
auto security_level = ConnectionSecurityLevel::PLAINTEXT;
|
||||||
|
if (args().m_enableCrypto) {
|
||||||
|
security_level = ConnectionSecurityLevel::ENCRYPTED;
|
||||||
|
if (args().check_client_certificates) {
|
||||||
|
security_level = ConnectionSecurityLevel::ENCRYPTED_AUTHENTICATED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ClientListener* listen = new ClientListener(
|
ClientListener* listen = new ClientListener(
|
||||||
address,
|
address,
|
||||||
new TCPSocketFactory(m_events, getSocketMultiplexer()),
|
new TCPSocketFactory(m_events, getSocketMultiplexer()),
|
||||||
m_events,
|
m_events, security_level);
|
||||||
args().m_enableCrypto);
|
|
||||||
|
|
||||||
m_events->adoptHandler(
|
m_events->adoptHandler(
|
||||||
m_events->forClientListener().connected(), listen,
|
m_events->forClientListener().connected(), listen,
|
||||||
|
|
|
@ -30,4 +30,5 @@ public:
|
||||||
String m_configFile;
|
String m_configFile;
|
||||||
Config* m_config;
|
Config* m_config;
|
||||||
String m_screenChangeScript;
|
String m_screenChangeScript;
|
||||||
|
bool check_client_certificates = true;
|
||||||
};
|
};
|
||||||
|
|
|
@ -127,6 +127,12 @@ Client::connect()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto security_level = ConnectionSecurityLevel::PLAINTEXT;
|
||||||
|
if (m_useSecureNetwork) {
|
||||||
|
// client always authenticates server
|
||||||
|
security_level = ConnectionSecurityLevel::ENCRYPTED_AUTHENTICATED;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// resolve the server hostname. do this every time we connect
|
// resolve the server hostname. do this every time we connect
|
||||||
// in case we couldn't resolve the address earlier or the address
|
// in case we couldn't resolve the address earlier or the address
|
||||||
|
@ -145,9 +151,8 @@ Client::connect()
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the socket
|
// create the socket
|
||||||
IDataSocket* socket = m_socketFactory->create(
|
IDataSocket* socket = m_socketFactory->create(ARCH->getAddrFamily(m_serverAddress.getAddress()),
|
||||||
ARCH->getAddrFamily(m_serverAddress.getAddress()),
|
security_level);
|
||||||
m_useSecureNetwork);
|
|
||||||
m_socket = dynamic_cast<TCPSocket*>(socket);
|
m_socket = dynamic_cast<TCPSocket*>(socket);
|
||||||
|
|
||||||
// filter socket messages, including a packetizing filter
|
// filter socket messages, including a packetizing filter
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
barrier -- mouse and keyboard sharing utility
|
||||||
|
Copyright (C) Barrier contributors
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BARRIER_LIB_NET_CONNECTION_SECURITY_LEVEL_H
|
||||||
|
#define BARRIER_LIB_NET_CONNECTION_SECURITY_LEVEL_H
|
||||||
|
|
||||||
|
enum class ConnectionSecurityLevel {
|
||||||
|
PLAINTEXT,
|
||||||
|
ENCRYPTED,
|
||||||
|
ENCRYPTED_AUTHENTICATED
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BARRIER_LIB_NET_CONNECTION_SECURITY_LEVEL_H
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include "common/IInterface.h"
|
#include "common/IInterface.h"
|
||||||
#include "arch/IArchNetwork.h"
|
#include "arch/IArchNetwork.h"
|
||||||
|
#include "net/ConnectionSecurityLevel.h"
|
||||||
|
|
||||||
class IDataSocket;
|
class IDataSocket;
|
||||||
class IListenSocket;
|
class IListenSocket;
|
||||||
|
@ -35,14 +36,12 @@ public:
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
//! Create data socket
|
//! Create data socket
|
||||||
virtual IDataSocket* create(
|
virtual IDataSocket* create(IArchNetwork::EAddressFamily family,
|
||||||
IArchNetwork::EAddressFamily family,
|
ConnectionSecurityLevel security_level) const = 0;
|
||||||
bool secure) const = 0;
|
|
||||||
|
|
||||||
//! Create listen socket
|
//! Create listen socket
|
||||||
virtual IListenSocket* createListen(
|
virtual IListenSocket* createListen(IArchNetwork::EAddressFamily family,
|
||||||
IArchNetwork::EAddressFamily family,
|
ConnectionSecurityLevel security_level) const = 0;
|
||||||
bool secure) const = 0;
|
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,11 +25,11 @@
|
||||||
#include "common/DataDirectories.h"
|
#include "common/DataDirectories.h"
|
||||||
#include "base/String.h"
|
#include "base/String.h"
|
||||||
|
|
||||||
SecureListenSocket::SecureListenSocket(
|
SecureListenSocket::SecureListenSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer,
|
||||||
IEventQueue* events,
|
IArchNetwork::EAddressFamily family,
|
||||||
SocketMultiplexer* socketMultiplexer,
|
ConnectionSecurityLevel security_level) :
|
||||||
IArchNetwork::EAddressFamily family) :
|
TCPListenSocket(events, socketMultiplexer, family),
|
||||||
TCPListenSocket(events, socketMultiplexer, family)
|
security_level_{security_level}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,10 +38,8 @@ SecureListenSocket::accept()
|
||||||
{
|
{
|
||||||
SecureSocket* socket = NULL;
|
SecureSocket* socket = NULL;
|
||||||
try {
|
try {
|
||||||
socket = new SecureSocket(
|
socket = new SecureSocket(m_events, m_socketMultiplexer,
|
||||||
m_events,
|
ARCH->acceptSocket(m_socket, NULL), security_level_);
|
||||||
m_socketMultiplexer,
|
|
||||||
ARCH->acceptSocket(m_socket, NULL));
|
|
||||||
socket->initSsl(true);
|
socket->initSsl(true);
|
||||||
|
|
||||||
if (socket != NULL) {
|
if (socket != NULL) {
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "net/TCPListenSocket.h"
|
#include "net/TCPListenSocket.h"
|
||||||
#include "common/stdset.h"
|
#include "common/stdset.h"
|
||||||
|
#include "ConnectionSecurityLevel.h"
|
||||||
|
|
||||||
class IEventQueue;
|
class IEventQueue;
|
||||||
class SocketMultiplexer;
|
class SocketMultiplexer;
|
||||||
|
@ -26,11 +27,13 @@ class IDataSocket;
|
||||||
|
|
||||||
class SecureListenSocket : public TCPListenSocket {
|
class SecureListenSocket : public TCPListenSocket {
|
||||||
public:
|
public:
|
||||||
SecureListenSocket(IEventQueue* events,
|
SecureListenSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer,
|
||||||
SocketMultiplexer* socketMultiplexer,
|
IArchNetwork::EAddressFamily family,
|
||||||
IArchNetwork::EAddressFamily family);
|
ConnectionSecurityLevel security_level);
|
||||||
|
|
||||||
// IListenSocket overrides
|
// IListenSocket overrides
|
||||||
virtual IDataSocket*
|
virtual IDataSocket*
|
||||||
accept();
|
accept();
|
||||||
|
private:
|
||||||
|
ConnectionSecurityLevel security_level_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -54,25 +54,24 @@ struct Ssl {
|
||||||
SSL* m_ssl;
|
SSL* m_ssl;
|
||||||
};
|
};
|
||||||
|
|
||||||
SecureSocket::SecureSocket(
|
SecureSocket::SecureSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer,
|
||||||
IEventQueue* events,
|
IArchNetwork::EAddressFamily family,
|
||||||
SocketMultiplexer* socketMultiplexer,
|
ConnectionSecurityLevel security_level) :
|
||||||
IArchNetwork::EAddressFamily family) :
|
|
||||||
TCPSocket(events, socketMultiplexer, family),
|
TCPSocket(events, socketMultiplexer, family),
|
||||||
m_ssl(nullptr),
|
m_ssl(nullptr),
|
||||||
m_secureReady(false),
|
m_secureReady(false),
|
||||||
m_fatal(false)
|
m_fatal(false),
|
||||||
|
security_level_{security_level}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SecureSocket::SecureSocket(
|
SecureSocket::SecureSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer,
|
||||||
IEventQueue* events,
|
ArchSocket socket, ConnectionSecurityLevel security_level) :
|
||||||
SocketMultiplexer* socketMultiplexer,
|
|
||||||
ArchSocket socket) :
|
|
||||||
TCPSocket(events, socketMultiplexer, socket),
|
TCPSocket(events, socketMultiplexer, socket),
|
||||||
m_ssl(nullptr),
|
m_ssl(nullptr),
|
||||||
m_secureReady(false),
|
m_secureReady(false),
|
||||||
m_fatal(false)
|
m_fatal(false),
|
||||||
|
security_level_{security_level}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,6 +361,11 @@ bool SecureSocket::load_certificates(const barrier::fs::path& path)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cert_verify_ignore_callback(X509_STORE_CTX*, void*)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SecureSocket::initContext(bool server)
|
SecureSocket::initContext(bool server)
|
||||||
{
|
{
|
||||||
|
@ -397,6 +401,14 @@ SecureSocket::initContext(bool server)
|
||||||
if (m_ssl->m_context == NULL) {
|
if (m_ssl->m_context == NULL) {
|
||||||
showError("");
|
showError("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (security_level_ == ConnectionSecurityLevel::ENCRYPTED_AUTHENTICATED) {
|
||||||
|
// We want to ask for peer certificate, but not verify it. If we don't ask for peer
|
||||||
|
// certificate, e.g. client won't send it.
|
||||||
|
SSL_CTX_set_verify(m_ssl->m_context, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
|
||||||
|
nullptr);
|
||||||
|
SSL_CTX_set_cert_verify_callback(m_ssl->m_context, cert_verify_ignore_callback, nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -437,6 +449,24 @@ SecureSocket::secureAccept(int socket)
|
||||||
|
|
||||||
// If not fatal and no retry, state is good
|
// If not fatal and no retry, state is good
|
||||||
if (retry == 0) {
|
if (retry == 0) {
|
||||||
|
if (security_level_ == ConnectionSecurityLevel::ENCRYPTED_AUTHENTICATED) {
|
||||||
|
if (verify_cert_fingerprint(
|
||||||
|
barrier::DataDirectories::trusted_clients_ssl_fingerprints_path())) {
|
||||||
|
LOG((CLOG_INFO "accepted secure socket"));
|
||||||
|
if (!ensure_peer_certificate()) {
|
||||||
|
retry = 0;
|
||||||
|
disconnect();
|
||||||
|
return -1;// Cert fail, error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG((CLOG_ERR "failed to verify server certificate fingerprint"));
|
||||||
|
retry = 0;
|
||||||
|
disconnect();
|
||||||
|
return -1; // Fingerprint failed, error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_secureReady = true;
|
m_secureReady = true;
|
||||||
LOG((CLOG_INFO "accepted secure socket"));
|
LOG((CLOG_INFO "accepted secure socket"));
|
||||||
if (CLOG->getFilter() >= kDEBUG1) {
|
if (CLOG->getFilter() >= kDEBUG1) {
|
||||||
|
@ -462,6 +492,12 @@ SecureSocket::secureAccept(int socket)
|
||||||
int
|
int
|
||||||
SecureSocket::secureConnect(int socket)
|
SecureSocket::secureConnect(int socket)
|
||||||
{
|
{
|
||||||
|
if (!load_certificates(barrier::DataDirectories::ssl_certificate_path())) {
|
||||||
|
LOG((CLOG_ERR "could not load client certificates"));
|
||||||
|
// FIXME: this is fatal error, but we current don't disconnect because whole logic in this
|
||||||
|
// function needs to be cleaned up
|
||||||
|
}
|
||||||
|
|
||||||
createSSL();
|
createSSL();
|
||||||
|
|
||||||
// attach the socket descriptor
|
// attach the socket descriptor
|
||||||
|
@ -491,9 +527,9 @@ SecureSocket::secureConnect(int socket)
|
||||||
retry = 0;
|
retry = 0;
|
||||||
// No error, set ready, process and return ok
|
// No error, set ready, process and return ok
|
||||||
m_secureReady = true;
|
m_secureReady = true;
|
||||||
if (verifyCertFingerprint()) {
|
if (verify_cert_fingerprint(barrier::DataDirectories::trusted_servers_ssl_fingerprints_path())) {
|
||||||
LOG((CLOG_INFO "connected to secure socket"));
|
LOG((CLOG_INFO "connected to secure socket"));
|
||||||
if (!showCertificate()) {
|
if (!ensure_peer_certificate()) {
|
||||||
disconnect();
|
disconnect();
|
||||||
return -1;// Cert fail, error
|
return -1;// Cert fail, error
|
||||||
}
|
}
|
||||||
|
@ -512,7 +548,7 @@ SecureSocket::secureConnect(int socket)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SecureSocket::showCertificate()
|
SecureSocket::ensure_peer_certificate()
|
||||||
{
|
{
|
||||||
X509* cert;
|
X509* cert;
|
||||||
char* line;
|
char* line;
|
||||||
|
@ -521,12 +557,12 @@ SecureSocket::showCertificate()
|
||||||
cert = SSL_get_peer_certificate(m_ssl->m_ssl);
|
cert = SSL_get_peer_certificate(m_ssl->m_ssl);
|
||||||
if (cert != NULL) {
|
if (cert != NULL) {
|
||||||
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
|
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
|
||||||
LOG((CLOG_INFO "server ssl certificate info: %s", line));
|
LOG((CLOG_INFO "peer ssl certificate info: %s", line));
|
||||||
OPENSSL_free(line);
|
OPENSSL_free(line);
|
||||||
X509_free(cert);
|
X509_free(cert);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
showError("server has no ssl certificate");
|
showError("peer has no ssl certificate");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -649,8 +685,7 @@ SecureSocket::disconnect()
|
||||||
sendEvent(getEvents()->forIStream().inputShutdown());
|
sendEvent(getEvents()->forIStream().inputShutdown());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool SecureSocket::verify_cert_fingerprint(const barrier::fs::path& fingerprint_db_path)
|
||||||
SecureSocket::verifyCertFingerprint()
|
|
||||||
{
|
{
|
||||||
// calculate received certificate fingerprint
|
// calculate received certificate fingerprint
|
||||||
barrier::FingerprintData fingerprint_sha1, fingerprint_sha256;
|
barrier::FingerprintData fingerprint_sha1, fingerprint_sha256;
|
||||||
|
@ -666,12 +701,10 @@ SecureSocket::verifyCertFingerprint()
|
||||||
}
|
}
|
||||||
|
|
||||||
// note: the GUI parses the following two lines of logs, don't change unnecessarily
|
// note: the GUI parses the following two lines of logs, don't change unnecessarily
|
||||||
LOG((CLOG_NOTE "server fingerprint (SHA1): %s (SHA256): %s",
|
LOG((CLOG_NOTE "peer fingerprint (SHA1): %s (SHA256): %s",
|
||||||
barrier::format_ssl_fingerprint(fingerprint_sha1.data).c_str(),
|
barrier::format_ssl_fingerprint(fingerprint_sha1.data).c_str(),
|
||||||
barrier::format_ssl_fingerprint(fingerprint_sha256.data).c_str()));
|
barrier::format_ssl_fingerprint(fingerprint_sha256.data).c_str()));
|
||||||
|
|
||||||
auto fingerprint_db_path = barrier::DataDirectories::trusted_servers_ssl_fingerprints_path();
|
|
||||||
|
|
||||||
// Provide debug hint as to what file is being used to verify fingerprint trust
|
// Provide debug hint as to what file is being used to verify fingerprint trust
|
||||||
LOG((CLOG_NOTE "fingerprint_db_path: %s", fingerprint_db_path.u8string().c_str()));
|
LOG((CLOG_NOTE "fingerprint_db_path: %s", fingerprint_db_path.u8string().c_str()));
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "ConnectionSecurityLevel.h"
|
||||||
#include "net/TCPSocket.h"
|
#include "net/TCPSocket.h"
|
||||||
#include "net/XSocket.h"
|
#include "net/XSocket.h"
|
||||||
#include "io/filesystem.h"
|
#include "io/filesystem.h"
|
||||||
|
@ -33,10 +34,10 @@ A secure socket using SSL.
|
||||||
*/
|
*/
|
||||||
class SecureSocket : public TCPSocket {
|
class SecureSocket : public TCPSocket {
|
||||||
public:
|
public:
|
||||||
SecureSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer, IArchNetwork::EAddressFamily family);
|
SecureSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer,
|
||||||
SecureSocket(IEventQueue* events,
|
IArchNetwork::EAddressFamily family, ConnectionSecurityLevel security_level);
|
||||||
SocketMultiplexer* socketMultiplexer,
|
SecureSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer,
|
||||||
ArchSocket socket);
|
ArchSocket socket, ConnectionSecurityLevel security_level);
|
||||||
~SecureSocket();
|
~SecureSocket();
|
||||||
|
|
||||||
// ISocket overrides
|
// ISocket overrides
|
||||||
|
@ -64,12 +65,12 @@ private:
|
||||||
void createSSL();
|
void createSSL();
|
||||||
int secureAccept(int s);
|
int secureAccept(int s);
|
||||||
int secureConnect(int s);
|
int secureConnect(int s);
|
||||||
bool showCertificate();
|
bool ensure_peer_certificate();
|
||||||
void checkResult(int n, int& retry);
|
void checkResult(int n, int& retry);
|
||||||
void showError(const std::string& reason);
|
void showError(const std::string& reason);
|
||||||
std::string getError();
|
std::string getError();
|
||||||
void disconnect();
|
void disconnect();
|
||||||
bool verifyCertFingerprint();
|
bool verify_cert_fingerprint(const barrier::fs::path& fingerprint_db_path);
|
||||||
|
|
||||||
MultiplexerJobStatus serviceConnect(ISocketMultiplexerJob*, bool, bool, bool);
|
MultiplexerJobStatus serviceConnect(ISocketMultiplexerJob*, bool, bool, bool);
|
||||||
MultiplexerJobStatus serviceAccept(ISocketMultiplexerJob*, bool, bool, bool);
|
MultiplexerJobStatus serviceAccept(ISocketMultiplexerJob*, bool, bool, bool);
|
||||||
|
@ -86,4 +87,5 @@ private:
|
||||||
Ssl* m_ssl;
|
Ssl* m_ssl;
|
||||||
bool m_secureReady;
|
bool m_secureReady;
|
||||||
bool m_fatal;
|
bool m_fatal;
|
||||||
|
ConnectionSecurityLevel security_level_ = ConnectionSecurityLevel::ENCRYPTED;
|
||||||
};
|
};
|
||||||
|
|
|
@ -40,11 +40,12 @@ TCPSocketFactory::~TCPSocketFactory()
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
IDataSocket*
|
IDataSocket* TCPSocketFactory::create(IArchNetwork::EAddressFamily family,
|
||||||
TCPSocketFactory::create(IArchNetwork::EAddressFamily family, bool secure) const
|
ConnectionSecurityLevel security_level) const
|
||||||
{
|
{
|
||||||
if (secure) {
|
if (security_level != ConnectionSecurityLevel::PLAINTEXT) {
|
||||||
SecureSocket* secureSocket = new SecureSocket(m_events, m_socketMultiplexer, family);
|
SecureSocket* secureSocket = new SecureSocket(m_events, m_socketMultiplexer, family,
|
||||||
|
security_level);
|
||||||
secureSocket->initSsl (false);
|
secureSocket->initSsl (false);
|
||||||
return secureSocket;
|
return secureSocket;
|
||||||
}
|
}
|
||||||
|
@ -53,12 +54,12 @@ TCPSocketFactory::create(IArchNetwork::EAddressFamily family, bool secure) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IListenSocket*
|
IListenSocket* TCPSocketFactory::createListen(IArchNetwork::EAddressFamily family,
|
||||||
TCPSocketFactory::createListen(IArchNetwork::EAddressFamily family, bool secure) const
|
ConnectionSecurityLevel security_level) const
|
||||||
{
|
{
|
||||||
IListenSocket* socket = NULL;
|
IListenSocket* socket = NULL;
|
||||||
if (secure) {
|
if (security_level != ConnectionSecurityLevel::PLAINTEXT) {
|
||||||
socket = new SecureListenSocket(m_events, m_socketMultiplexer, family);
|
socket = new SecureListenSocket(m_events, m_socketMultiplexer, family, security_level);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
socket = new TCPListenSocket(m_events, m_socketMultiplexer, family);
|
socket = new TCPListenSocket(m_events, m_socketMultiplexer, family);
|
||||||
|
|
|
@ -31,12 +31,11 @@ public:
|
||||||
virtual ~TCPSocketFactory();
|
virtual ~TCPSocketFactory();
|
||||||
|
|
||||||
// ISocketFactory overrides
|
// ISocketFactory overrides
|
||||||
virtual IDataSocket* create(
|
virtual IDataSocket* create(IArchNetwork::EAddressFamily family,
|
||||||
IArchNetwork::EAddressFamily family,
|
ConnectionSecurityLevel security_level) const;
|
||||||
bool secure) const;
|
|
||||||
virtual IListenSocket* createListen(
|
virtual IListenSocket* createListen(IArchNetwork::EAddressFamily family,
|
||||||
IArchNetwork::EAddressFamily family,
|
ConnectionSecurityLevel security_level) const;
|
||||||
bool secure) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IEventQueue* m_events;
|
IEventQueue* m_events;
|
||||||
|
|
|
@ -36,18 +36,17 @@
|
||||||
ClientListener::ClientListener(const NetworkAddress& address,
|
ClientListener::ClientListener(const NetworkAddress& address,
|
||||||
ISocketFactory* socketFactory,
|
ISocketFactory* socketFactory,
|
||||||
IEventQueue* events,
|
IEventQueue* events,
|
||||||
bool enableCrypto) :
|
ConnectionSecurityLevel security_level) :
|
||||||
m_socketFactory(socketFactory),
|
m_socketFactory(socketFactory),
|
||||||
m_server(NULL),
|
m_server(NULL),
|
||||||
m_events(events),
|
m_events(events),
|
||||||
m_useSecureNetwork(enableCrypto)
|
security_level_{security_level}
|
||||||
{
|
{
|
||||||
assert(m_socketFactory != NULL);
|
assert(m_socketFactory != NULL);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
m_listen = m_socketFactory->createListen(
|
m_listen = m_socketFactory->createListen(ARCH->getAddrFamily(address.getAddress()),
|
||||||
ARCH->getAddrFamily(address.getAddress()),
|
security_level);
|
||||||
m_useSecureNetwork);
|
|
||||||
|
|
||||||
// setup event handler
|
// setup event handler
|
||||||
m_events->adoptHandler(m_events->forIListenSocket().connecting(),
|
m_events->adoptHandler(m_events->forIListenSocket().connecting(),
|
||||||
|
@ -140,7 +139,7 @@ ClientListener::handleClientConnecting(const Event&, void*)
|
||||||
|
|
||||||
// When using non SSL, server accepts clients immediately, while SSL
|
// When using non SSL, server accepts clients immediately, while SSL
|
||||||
// has to call secure accept which may require retry
|
// has to call secure accept which may require retry
|
||||||
if (!m_useSecureNetwork) {
|
if (security_level_ == ConnectionSecurityLevel::PLAINTEXT) {
|
||||||
m_events->addEvent(Event(m_events->forClientListener().accepted(),
|
m_events->addEvent(Event(m_events->forClientListener().accepted(),
|
||||||
socket->getEventTarget()));
|
socket->getEventTarget()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "base/Event.h"
|
#include "base/Event.h"
|
||||||
#include "common/stddeque.h"
|
#include "common/stddeque.h"
|
||||||
#include "common/stdset.h"
|
#include "common/stdset.h"
|
||||||
|
#include "net/ConnectionSecurityLevel.h"
|
||||||
|
|
||||||
class ClientProxy;
|
class ClientProxy;
|
||||||
class ClientProxyUnknown;
|
class ClientProxyUnknown;
|
||||||
|
@ -36,10 +37,8 @@ class IDataSocket;
|
||||||
class ClientListener {
|
class ClientListener {
|
||||||
public:
|
public:
|
||||||
// The factories are adopted.
|
// The factories are adopted.
|
||||||
ClientListener(const NetworkAddress&,
|
ClientListener(const NetworkAddress&, ISocketFactory*, IEventQueue* events,
|
||||||
ISocketFactory*,
|
ConnectionSecurityLevel security_level);
|
||||||
IEventQueue* events,
|
|
||||||
bool enableCrypto);
|
|
||||||
~ClientListener();
|
~ClientListener();
|
||||||
|
|
||||||
//! @name manipulators
|
//! @name manipulators
|
||||||
|
@ -86,6 +85,6 @@ private:
|
||||||
WaitingClients m_waitingClients;
|
WaitingClients m_waitingClients;
|
||||||
Server* m_server;
|
Server* m_server;
|
||||||
IEventQueue* m_events;
|
IEventQueue* m_events;
|
||||||
bool m_useSecureNetwork;
|
ConnectionSecurityLevel security_level_;
|
||||||
ClientSockets m_clientSockets;
|
ClientSockets m_clientSockets;
|
||||||
};
|
};
|
||||||
|
|
|
@ -115,7 +115,8 @@ TEST_F(NetworkTests, sendToClient_mockData)
|
||||||
// server
|
// server
|
||||||
SocketMultiplexer serverSocketMultiplexer;
|
SocketMultiplexer serverSocketMultiplexer;
|
||||||
TCPSocketFactory* serverSocketFactory = new TCPSocketFactory(&m_events, &serverSocketMultiplexer);
|
TCPSocketFactory* serverSocketFactory = new TCPSocketFactory(&m_events, &serverSocketMultiplexer);
|
||||||
ClientListener listener(serverAddress, serverSocketFactory, &m_events, false);
|
ClientListener listener(serverAddress, serverSocketFactory, &m_events,
|
||||||
|
ConnectionSecurityLevel::PLAINTEXT);
|
||||||
NiceMock<MockScreen> serverScreen;
|
NiceMock<MockScreen> serverScreen;
|
||||||
NiceMock<MockPrimaryClient> primaryClient;
|
NiceMock<MockPrimaryClient> primaryClient;
|
||||||
NiceMock<MockConfig> serverConfig;
|
NiceMock<MockConfig> serverConfig;
|
||||||
|
@ -173,7 +174,8 @@ TEST_F(NetworkTests, sendToClient_mockFile)
|
||||||
// server
|
// server
|
||||||
SocketMultiplexer serverSocketMultiplexer;
|
SocketMultiplexer serverSocketMultiplexer;
|
||||||
TCPSocketFactory* serverSocketFactory = new TCPSocketFactory(&m_events, &serverSocketMultiplexer);
|
TCPSocketFactory* serverSocketFactory = new TCPSocketFactory(&m_events, &serverSocketMultiplexer);
|
||||||
ClientListener listener(serverAddress, serverSocketFactory, &m_events, false);
|
ClientListener listener(serverAddress, serverSocketFactory, &m_events,
|
||||||
|
ConnectionSecurityLevel::PLAINTEXT);
|
||||||
NiceMock<MockScreen> serverScreen;
|
NiceMock<MockScreen> serverScreen;
|
||||||
NiceMock<MockPrimaryClient> primaryClient;
|
NiceMock<MockPrimaryClient> primaryClient;
|
||||||
NiceMock<MockConfig> serverConfig;
|
NiceMock<MockConfig> serverConfig;
|
||||||
|
@ -230,7 +232,8 @@ TEST_F(NetworkTests, sendToServer_mockData)
|
||||||
// server
|
// server
|
||||||
SocketMultiplexer serverSocketMultiplexer;
|
SocketMultiplexer serverSocketMultiplexer;
|
||||||
TCPSocketFactory* serverSocketFactory = new TCPSocketFactory(&m_events, &serverSocketMultiplexer);
|
TCPSocketFactory* serverSocketFactory = new TCPSocketFactory(&m_events, &serverSocketMultiplexer);
|
||||||
ClientListener listener(serverAddress, serverSocketFactory, &m_events, false);
|
ClientListener listener(serverAddress, serverSocketFactory, &m_events,
|
||||||
|
ConnectionSecurityLevel::PLAINTEXT);
|
||||||
NiceMock<MockScreen> serverScreen;
|
NiceMock<MockScreen> serverScreen;
|
||||||
NiceMock<MockPrimaryClient> primaryClient;
|
NiceMock<MockPrimaryClient> primaryClient;
|
||||||
NiceMock<MockConfig> serverConfig;
|
NiceMock<MockConfig> serverConfig;
|
||||||
|
@ -287,7 +290,8 @@ TEST_F(NetworkTests, sendToServer_mockFile)
|
||||||
// server
|
// server
|
||||||
SocketMultiplexer serverSocketMultiplexer;
|
SocketMultiplexer serverSocketMultiplexer;
|
||||||
TCPSocketFactory* serverSocketFactory = new TCPSocketFactory(&m_events, &serverSocketMultiplexer);
|
TCPSocketFactory* serverSocketFactory = new TCPSocketFactory(&m_events, &serverSocketMultiplexer);
|
||||||
ClientListener listener(serverAddress, serverSocketFactory, &m_events, false);
|
ClientListener listener(serverAddress, serverSocketFactory, &m_events,
|
||||||
|
ConnectionSecurityLevel::PLAINTEXT);
|
||||||
NiceMock<MockScreen> serverScreen;
|
NiceMock<MockScreen> serverScreen;
|
||||||
NiceMock<MockPrimaryClient> primaryClient;
|
NiceMock<MockPrimaryClient> primaryClient;
|
||||||
NiceMock<MockConfig> serverConfig;
|
NiceMock<MockConfig> serverConfig;
|
||||||
|
|
Loading…
Reference in New Issue