diff --git a/src/gui/gui.pro b/src/gui/gui.pro
index 4f8fcabb..7f2670be 100644
--- a/src/gui/gui.pro
+++ b/src/gui/gui.pro
@@ -55,7 +55,8 @@ SOURCES += src/main.cpp \
src/WebClient.cpp \
src/PluginWizardPage.cpp \
src/PluginManager.cpp \
- src/CoreInterface.cpp
+ src/CoreInterface.cpp \
+ src/Fingerprint.cpp
HEADERS += src/MainWindow.h \
src/AboutDialog.h \
src/ServerConfig.h \
@@ -97,7 +98,8 @@ HEADERS += src/MainWindow.h \
src/PluginWizardPage.h \
src/ProcessorArch.h \
src/PluginManager.h \
- src/CoreInterface.h
+ src/CoreInterface.h \
+ src/Fingerprint.h
RESOURCES += res/Synergy.qrc
RC_FILE = res/win/Synergy.rc
macx {
diff --git a/src/gui/src/Fingerprint.cpp b/src/gui/src/Fingerprint.cpp
new file mode 100644
index 00000000..0ff15a44
--- /dev/null
+++ b/src/gui/src/Fingerprint.cpp
@@ -0,0 +1,104 @@
+/*
+ * synergy -- mouse and keyboard sharing utility
+ * Copyright (C) 2015 Synergy Si Ltd.
+ *
+ * This package is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * found in the file COPYING 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 .
+ */
+
+#include "Fingerprint.h"
+
+#include "CoreInterface.h"
+
+#include
+#include
+
+static const char kDirName[] = "ssl/fingerprints";
+static const char kLocalFilename[] = "local.txt";
+static const char kTrustedServersFilename[] = "trusted-servers.txt";
+static const char kTrustedClientsFilename[] = "trusted-clients.txt";
+
+Fingerprint::Fingerprint(const QString& filename)
+{
+ m_Filename = filename;
+}
+
+void Fingerprint::trust(const QString& fingerprintText)
+{
+ CoreInterface coreInterface;
+ QString profileDir = coreInterface.getProfileDir();
+
+ QString dirName = QString("%1/%2")
+ .arg(profileDir)
+ .arg(kDirName);
+
+ QDir dir(dirName);
+ if (!dir.exists()) {
+ dir.mkpath(".");
+ }
+
+ QString path = QString("%1/%2").arg(dirName).arg(m_Filename);
+ QFile file(path);
+ if (file.open(QIODevice::Append))
+ {
+ QTextStream out(&file);
+ out << fingerprintText << "\n";
+ file.close();
+ }
+}
+
+bool Fingerprint::check(const QString& fingerprintText)
+{
+ CoreInterface coreInterface;
+ QString profileDir = coreInterface.getProfileDir();
+
+ QString dirName = QString("%1/%2")
+ .arg(profileDir)
+ .arg(kDirName);
+
+ if (!QDir(dirName).exists()) {
+ return false;
+ }
+
+ QString path = QString("%1/%2").arg(dirName).arg(m_Filename);
+ QFile file(path);
+
+ if (file.open(QIODevice::ReadOnly))
+ {
+ QTextStream in(&file);
+ while (!in.atEnd())
+ {
+ QString trusted = in.readLine();
+ if (fingerprintText == trusted) {
+ return true;
+ }
+ }
+ file.close();
+ }
+
+ return false;
+}
+
+Fingerprint Fingerprint::local()
+{
+ return Fingerprint(kLocalFilename);
+}
+
+Fingerprint Fingerprint::trustedServers()
+{
+ return Fingerprint(kTrustedServersFilename);
+}
+
+Fingerprint Fingerprint::trustedClients()
+{
+ return Fingerprint(kTrustedClientsFilename);
+}
diff --git a/src/gui/src/Fingerprint.h b/src/gui/src/Fingerprint.h
new file mode 100644
index 00000000..d494af0b
--- /dev/null
+++ b/src/gui/src/Fingerprint.h
@@ -0,0 +1,38 @@
+/*
+ * synergy -- mouse and keyboard sharing utility
+ * Copyright (C) 2015 Synergy Si Ltd.
+ *
+ * This package is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * found in the file COPYING 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 .
+ */
+
+#pragma once
+
+#include
+
+class Fingerprint
+{
+private:
+ Fingerprint(const QString& filename);
+
+public:
+ void trust(const QString& fingerprintText);
+ bool check(const QString& fingerprintText);
+
+public:
+ static Fingerprint local();
+ static Fingerprint trustedServers();
+ static Fingerprint trustedClients();
+
+private:
+ QString m_Filename;
+};
diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp
index 234370ed..c4e8b0fc 100644
--- a/src/gui/src/MainWindow.cpp
+++ b/src/gui/src/MainWindow.cpp
@@ -21,6 +21,8 @@
#include
#include "MainWindow.h"
+
+#include "Fingerprint.h"
#include "AboutDialog.h"
#include "ServerConfigDialog.h"
#include "SettingsDialog.h"
@@ -396,32 +398,48 @@ void MainWindow::updateStateFromLogLine(const QString &line)
setSynergyState(synergyConnected);
}
+ checkFingerprint(line);
+}
+
+void MainWindow::checkFingerprint(const QString& line)
+{
QRegExp fingerprintRegex(".*server fingerprint: ([A-F0-9:]+)");
- if (fingerprintRegex.exactMatch(line)) {
+ if (!fingerprintRegex.exactMatch(line)) {
+ return;
+ }
- QString fingerprint = fingerprintRegex.cap(1);
- QMessageBox::StandardButton fingerprintReply =
- QMessageBox::information(
- this, tr("Security question"),
- tr("Do you trust this fingerprint?\n\n"
- "%1\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(fingerprint),
- QMessageBox::Yes | QMessageBox::No);
+ QString fingerprint = fingerprintRegex.cap(1);
+ if (Fingerprint::trustedServers().check(fingerprint)) {
+ return;
+ }
- if (fingerprintReply == QMessageBox::Yes) {
- // TODO: save to file
- qDebug() << "fingerprint: " << fingerprint;
- }
- else {
- stopSynergy();
- }
+ QMessageBox::StandardButton fingerprintReply =
+ QMessageBox::information(
+ this, tr("Security question"),
+ tr("Do you trust this fingerprint?\n\n"
+ "%1\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(fingerprint),
+ QMessageBox::Yes | QMessageBox::No);
+
+ if (fingerprintReply == QMessageBox::Yes) {
+ // restart core process after trusting fingerprint.
+ Fingerprint::trustedServers().trust(fingerprint);
+ startSynergy();
+ }
+ else {
+ // on all platforms, the core process will stop if the
+ // fingerprint is not trusted, so technically the stop
+ // isn't really needed. however on windows, the core
+ // process will keep trying (and failing) unless we
+ // tell it to stop.
+ stopSynergy();
}
}
@@ -479,7 +497,11 @@ void MainWindow::startSynergy()
}
#if defined(Q_OS_WIN)
- args << "--profile-dir" << getProfileDirectoryForArg();
+ // on windows, the profile directory changes depending on the user that
+ // launched the process (e.g. when launched with elevation). setting the
+ // profile dir on launch ensures it uses the same profile dir is used
+ // no matter how its relaunched.
+ args << "--profile-dir" << getProfileRootForArg();
#endif
if ((synergyType() == synergyClient && !clientArgs(args, app))
@@ -1251,25 +1273,17 @@ void MainWindow::bonjourInstallFinished()
m_pCheckBoxAutoConfig->setChecked(true);
}
-QString MainWindow::getProfileDirectory()
+QString MainWindow::getProfileRootForArg()
{
+ CoreInterface coreInterface;
+ QString dir = coreInterface.getProfileDir();
+
+ // HACK: strip our app name since we're returning the root dir.
#if defined(Q_OS_WIN)
-
- QString qtDataDir = QDesktopServices::storageLocation(
- QDesktopServices::DataLocation);
-
- // HACK: core wants the base app data dir, this seems like a very hacky
- // way to get it (maybe consider using %LOCALAPPDATA% instead?)
- return qtDataDir.replace("\\Synergy\\Synergy", "");
-
+ dir.replace("\\Synergy", "");
#else
-
- return "";
-
+ dir.replace("/.synergy", "");
#endif
-}
-QString MainWindow::getProfileDirectoryForArg()
-{
- return QString("\"%1\"").arg(getProfileDirectory());
+ return QString("\"%1\"").arg(dir);
}
diff --git a/src/gui/src/MainWindow.h b/src/gui/src/MainWindow.h
index b82984cf..9ab1b17b 100644
--- a/src/gui/src/MainWindow.h
+++ b/src/gui/src/MainWindow.h
@@ -165,8 +165,8 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
void downloadBonjour();
void promptAutoConfig();
void updateEdition();
- QString getProfileDirectory();
- QString getProfileDirectoryForArg();
+ QString getProfileRootForArg();
+ void checkFingerprint(const QString& line);
private:
QSettings& m_Settings;