diff --git a/src/gui/gui.pro b/src/gui/gui.pro index 527e7116..920f8472 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -63,7 +63,8 @@ HEADERS += src/MainWindow.h \ src/SetupWizard.h \ src/IpcClient.h \ src/IpcReader.h \ - src/Ipc.h + src/Ipc.h \ + src/CryptoMode.h RESOURCES += res/Synergy.qrc RC_FILE = res/win/Synergy.rc TRANSLATIONS = res/lang/nl_NL.ts diff --git a/src/gui/res/SettingsDialogBase.ui b/src/gui/res/SettingsDialogBase.ui index 0fc6f436..b58bfbd0 100644 --- a/src/gui/res/SettingsDialogBase.ui +++ b/src/gui/res/SettingsDialogBase.ui @@ -6,22 +6,144 @@ 0 0 - 383 - 387 + 369 + 459 Settings - - + + + + + &Startup + + + + + + &Start Synergy after logging in + + + + + + + &Automatically start server/client + + + + + + + &Hide when server/client starts + + + + + + + + + + true + + + + 0 + 0 + + + + &Encryption + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + + 75 + 0 + + + + &Mode: + + + m_pComboCryptoMode + + + + + + + + OFB (Output Feedback) + + + + + CFB (Cipher Feedback) + + + + + CTR (Counter) + + + + + GCM (Galois/Counter) + + + + + Disable encryption + + + + + + + + Pass&word: + + + m_pLineEditCryptoPass + + + + + + + true + + + QLineEdit::Password + + + + + + + &Advanced - + + + + 75 + 0 + + Sc&reen name: @@ -30,7 +152,7 @@ - + true @@ -47,24 +169,7 @@ - - - - &Interface: - - - m_pLineEditInterface - - - - - - - true - - - - + true @@ -83,17 +188,34 @@ - - + + - &Process mode: + &Interface: m_pLineEditInterface - + + + + true + + + + + + + &Process mode: + + + m_pComboProcessMode + + + + @@ -110,24 +232,32 @@ - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - + + + + 0 + 0 + + Logging - + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + false + + + + + 75 + 0 + + &Logging level: @@ -136,31 +266,7 @@ - - - - Log to file: - - - - - - - false - - - - - - - false - - - Browse... - - - - + @@ -199,40 +305,34 @@ - - - - - - - &Startup - - - - + + - &Start Synergy after logging in + Log to file: - - - - &Automatically start server/client + + + + false - - + + + + false + - &Hide when server/client starts + Browse... - + Qt::Vertical @@ -245,6 +345,16 @@ + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + @@ -254,7 +364,6 @@ m_pComboLogLevel m_pCheckBoxLogToFile m_pLineEditLogFilename - m_pButtonBrowseLog buttonBox diff --git a/src/gui/res/SetupWizardBase.ui b/src/gui/res/SetupWizardBase.ui index 8b98e791..928fcc39 100644 --- a/src/gui/res/SetupWizardBase.ui +++ b/src/gui/res/SetupWizardBase.ui @@ -125,6 +125,310 @@ + + + + 0 + 0 + + + + Encryption + + + + + + Network traffic can be easily monitored. Using encryption can reduce the risk that sensitive information will be revealed to others (for example, passwords). + + + true + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + Choose a random encryption mode. The mode must be the same on both the client and server. + + + true + + + + + + + QFormLayout::ExpandingFieldsGrow + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 75 + true + + + + &Mode: + + + 10 + + + m_pComboCryptoMode + + + + + + + + 0 + 0 + + + + + 200 + 0 + + + + + + + + + + OFB (Output Feedback) + + + + + CFB (Cipher Feedback) + + + + + CTR (Counter) + + + + + GCM (Galois/Counter) + + + + + Disable encryption + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 10 + + + + + + + + + 0 + 0 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">A longer password will provide stronger encryption. It is a good idea to use 20 characters or more.</span></p></body></html> + + + true + + + + + + + + + + 100 + 0 + + + + + 75 + true + + + + &Password: + + + 10 + + + m_pLineEditCryptoPass + + + + + + + true + + + + 0 + 0 + + + + + 200 + 0 + + + + + 0 + 0 + + + + + 0 + 0 + + + + QLineEdit::Password + + + + + + + + 100 + 0 + + + + + 75 + true + + + + &Confirm: + + + 10 + + + m_pLineEditCryptoPassConfirm + + + + + + + true + + + + 0 + 0 + + + + + 200 + 0 + + + + QLineEdit::Password + + + + + + + + + Qt::Vertical + + + + 20 + 100 + + + + + + diff --git a/src/gui/src/AppConfig.cpp b/src/gui/src/AppConfig.cpp index 076c789f..ba3c1de9 100644 --- a/src/gui/src/AppConfig.cpp +++ b/src/gui/src/AppConfig.cpp @@ -54,7 +54,9 @@ AppConfig::AppConfig(QSettings* settings) : m_AutoStart(false), m_AutoHide(false), m_AutoStartPrompt(false), - m_WizardHasRun(false), + m_WizardLastRun(0), + m_CryptoPass(), + m_CryptoMode(), m_ProcessMode(DEFAULT_PROCESS_MODE) { Q_ASSERT(m_pSettings); @@ -154,8 +156,10 @@ void AppConfig::loadSettings() m_AutoStart = settings().value("autoStart", false).toBool(); m_AutoHide = settings().value("autoHide", true).toBool(); m_AutoStartPrompt = settings().value("autoStartPrompt", true).toBool(); - m_WizardHasRun = settings().value("wizardHasRun", false).toBool(); + m_WizardLastRun = settings().value("wizardLastRun", 0).toInt(); m_ProcessMode = (ProcessMode)settings().value("processMode2", DEFAULT_PROCESS_MODE).toInt(); + m_CryptoPass = settings().value("cryptoPass", "").toString(); + m_CryptoMode = (CryptoMode)settings().value("cryptoMode", Disabled).toInt(); } void AppConfig::saveSettings() @@ -170,6 +174,53 @@ void AppConfig::saveSettings() settings().setValue("autoStart", m_AutoStart); settings().setValue("autoHide", m_AutoHide); settings().setValue("autoStartPrompt", m_AutoStartPrompt); - settings().setValue("wizardHasRun", m_WizardHasRun); + settings().setValue("wizardLastRun", kWizardVersion); settings().setValue("processMode2", m_ProcessMode); + settings().setValue("cryptoPass", m_CryptoPass); + settings().setValue("cryptoMode", m_CryptoMode); +} + +QString AppConfig::hash(const QString& string) +{ + QByteArray data = string.toUtf8(); + QByteArray hash = QCryptographicHash::hash(data, QCryptographicHash::Md5); + return hash.toHex(); +} + +void AppConfig::setCryptoPass(const QString &s) +{ + // clear field to user doesn't get confused. + if (s.isEmpty()) + { + m_CryptoPass.clear(); + return; + } + + // only hash if password changes -- don't re-hash the hash. + if (m_CryptoPass != s) + { + m_CryptoPass = hash(s); + } +} + +QString AppConfig::cryptoModeString() const +{ + switch (cryptoMode()) + { + case OFB: + return "ofb"; + + case CFB: + return "cfb"; + + case CTR: + return "ctr"; + + case GCM: + return "gcm"; + + default: + qCritical() << "invalid crypto mode"; + return ""; + } } diff --git a/src/gui/src/AppConfig.h b/src/gui/src/AppConfig.h index ddce9706..65ab1d9b 100644 --- a/src/gui/src/AppConfig.h +++ b/src/gui/src/AppConfig.h @@ -21,6 +21,13 @@ #define APPCONFIG_H #include +#include "CryptoMode.h" + +// this should be incremented each time a new page is added. this is +// saved to settings when the user finishes running the wizard. if +// the saved wizard version is lower than this number, the wizard +// will be displayed. +const int kWizardVersion = 1; class QSettings; class SettingsDialog; @@ -52,8 +59,11 @@ class AppConfig bool autoStart() const { return m_AutoStart; } bool autoHide() const { return m_AutoHide; } bool autoStartPrompt() const { return m_AutoStartPrompt; } - bool wizardHasRun() const { return m_WizardHasRun; } + const QString& cryptoPass() const { return m_CryptoPass; } + CryptoMode cryptoMode() const { return m_CryptoMode; } + QString cryptoModeString() const; ProcessMode processMode() const { return m_ProcessMode; } + bool wizardShouldRun() const { return m_WizardLastRun < kWizardVersion; } QString synergysName() const { return m_SynergysName; } QString synergycName() const { return m_SynergycName; } @@ -75,12 +85,16 @@ class AppConfig void setAutoStart(bool b); void setAutoHide(bool b) { m_AutoHide = b; } void setAutoStartPrompt(bool b) { m_AutoStartPrompt = b; } - void setWizardHasRun(bool b) { m_WizardHasRun = b; } + void setCryptoMode(CryptoMode c) { m_CryptoMode = c; } void setProcessMode(ProcessMode p) { m_ProcessMode = p; } + void setWizardHasRun() { m_WizardLastRun = kWizardVersion; } void loadSettings(); void saveSettings(); + void setCryptoPass(const QString& s); + static QString hash(const QString& string); + private: QSettings* m_pSettings; bool m_AutoConnect; @@ -93,7 +107,9 @@ class AppConfig bool m_AutoStart; bool m_AutoHide; bool m_AutoStartPrompt; - bool m_WizardHasRun; + int m_WizardLastRun; + QString m_CryptoPass; + CryptoMode m_CryptoMode; ProcessMode m_ProcessMode; static const char m_SynergysName[]; diff --git a/src/gui/src/CryptoMode.h b/src/gui/src/CryptoMode.h new file mode 100644 index 00000000..5db9964c --- /dev/null +++ b/src/gui/src/CryptoMode.h @@ -0,0 +1,26 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2013 Bolton Software 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 + +enum CryptoMode { + Disabled, + OFB, + CFB, + CTR, + GCM +}; diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 64b333c4..b9343006 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -380,6 +380,12 @@ void MainWindow::startSynergy() if (!appConfig().screenName().isEmpty()) args << "--name" << appConfig().screenName(); + if (appConfig().cryptoMode() != Disabled) + { + args << "--crypto-mode" << appConfig().cryptoModeString(); + args << "--crypto-pass" << appConfig().cryptoPass(); + } + if (desktopMode) { setSynergyProcess(new QProcess(this)); diff --git a/src/gui/src/SettingsDialog.cpp b/src/gui/src/SettingsDialog.cpp index fc425c95..5ec01122 100644 --- a/src/gui/src/SettingsDialog.cpp +++ b/src/gui/src/SettingsDialog.cpp @@ -20,6 +20,7 @@ #include #include +#include #include "AppConfig.h" @@ -40,10 +41,24 @@ SettingsDialog::SettingsDialog(QWidget* parent, AppConfig& config) : m_pLineEditLogFilename->setText(appConfig().logFilename()); m_pCheckBoxAutoStart->setChecked(appConfig().autoStart()); m_pCheckBoxAutoHide->setChecked(appConfig().autoHide()); + m_pComboCryptoMode->setCurrentIndex(getCryptoModeIndex(appConfig().cryptoMode())); + m_pLineEditCryptoPass->setText(appConfig().cryptoPass()); } void SettingsDialog::accept() { + const QString& cryptoPass = m_pLineEditCryptoPass->text(); + CryptoMode cryptoMode = parseCryptoMode(m_pComboCryptoMode->currentText()); + if ((cryptoMode != Disabled) && cryptoPass.isEmpty()) + { + QMessageBox message; + message.setWindowTitle("Settings"); + message.setIcon(QMessageBox::Information); + message.setText(tr("Encryption password must not be empty.")); + message.exec(); + return; + } + appConfig().setAutoConnect(m_pCheckBoxAutoConnect->isChecked()); appConfig().setScreenName(m_pLineEditScreenName->text()); appConfig().setPort(m_pSpinBoxPort->value()); @@ -54,7 +69,9 @@ void SettingsDialog::accept() appConfig().setLogFilename(m_pLineEditLogFilename->text()); appConfig().setAutoStart(m_pCheckBoxAutoStart->isChecked()); appConfig().setAutoHide(m_pCheckBoxAutoHide->isChecked()); - + appConfig().setCryptoMode(cryptoMode); + appConfig().setCryptoPass(cryptoPass); + appConfig().saveSettings(); QDialog::accept(); } @@ -78,3 +95,56 @@ void SettingsDialog::on_m_pButtonBrowseLog_clicked() m_pLineEditLogFilename->setText(fileName); } } + +void SettingsDialog::on_m_pComboCryptoMode_currentIndexChanged(int index) +{ + bool enabled = parseCryptoMode(m_pComboCryptoMode->currentText()) != Disabled; + m_pLineEditCryptoPass->setEnabled(enabled); + if (!enabled) + { + m_pLineEditCryptoPass->clear(); + } +} + +int SettingsDialog::getCryptoModeIndex(const CryptoMode& mode) const +{ + switch (mode) + { + case OFB: + return m_pComboCryptoMode->findText("OFB", Qt::MatchStartsWith); + + case CFB: + return m_pComboCryptoMode->findText("CFB", Qt::MatchStartsWith); + + case CTR: + return m_pComboCryptoMode->findText("CTR", Qt::MatchStartsWith); + + case GCM: + return m_pComboCryptoMode->findText("GCM", Qt::MatchStartsWith); + + default: + return m_pComboCryptoMode->findText("Disable", Qt::MatchStartsWith); + } +} + +CryptoMode SettingsDialog::parseCryptoMode(const QString& s) +{ + if (s.startsWith("OFB")) + { + return OFB; + } + else if (s.startsWith("CFB")) + { + return CFB; + } + else if (s.startsWith("CTR")) + { + return CTR; + } + else if (s.startsWith("GCM")) + { + return GCM; + } + + return Disabled; +} diff --git a/src/gui/src/SettingsDialog.h b/src/gui/src/SettingsDialog.h index 603328b2..ab67ca98 100644 --- a/src/gui/src/SettingsDialog.h +++ b/src/gui/src/SettingsDialog.h @@ -22,6 +22,7 @@ #include #include "ui_SettingsDialogBase.h" +#include "CryptoMode.h" class AppConfig; @@ -39,9 +40,12 @@ class SettingsDialog : public QDialog, public Ui::SettingsDialogBase AppConfig& appConfig() { return m_AppConfig; } private: + int getCryptoModeIndex(const CryptoMode& mode) const; + CryptoMode parseCryptoMode(const QString& s); AppConfig& m_AppConfig; private slots: + void on_m_pComboCryptoMode_currentIndexChanged(int index); void on_m_pCheckBoxLogToFile_stateChanged(int ); void on_m_pButtonBrowseLog_clicked(); }; diff --git a/src/gui/src/SetupWizard.cpp b/src/gui/src/SetupWizard.cpp index e82b6b54..98e91c1f 100644 --- a/src/gui/src/SetupWizard.cpp +++ b/src/gui/src/SetupWizard.cpp @@ -45,7 +45,7 @@ SetupWizard::SetupWizard(MainWindow& mainWindow, bool startMain) : #endif - connect(this, SIGNAL(finished(int)), this, SLOT(handlefinished())); + connect(this, SIGNAL(finished(int)), this, SLOT(handleFinished())); connect(m_pServerRadioButton, SIGNAL(toggled(bool)), m_MainWindow.m_pGroupServer, SLOT(setChecked(bool))); connect(m_pClientRadioButton, SIGNAL(toggled(bool)), m_MainWindow.m_pGroupClient, SLOT(setChecked(bool))); } @@ -60,28 +60,59 @@ bool SetupWizard::validateCurrentPage() message.setWindowTitle(tr("Setup Synergy")); message.setIcon(QMessageBox::Information); - bool result = false; if (currentPage() == m_pNodePage) { - result = m_pClientRadioButton->isChecked() || + bool result = m_pClientRadioButton->isChecked() || m_pServerRadioButton->isChecked(); if (!result) { message.setText(tr("Please select an option.")); message.exec(); + return false; } } - return result; + else if (currentPage() == m_pCryptoPage) + { + QString modeText = m_pComboCryptoMode->currentText(); + if (modeText.isEmpty()) + { + message.setText(tr("Encryption mode required.")); + message.exec(); + return false; + } + + if (parseCryptoMode(modeText) != Disabled) + { + if (m_pLineEditCryptoPass->text().isEmpty()) + { + message.setText(tr("Encryption password required.")); + message.exec(); + return false; + } + + if (m_pLineEditCryptoPass->text() != m_pLineEditCryptoPassConfirm->text()) + { + message.setText(tr("Encryption password and confirmation do not match.")); + message.exec(); + return false; + } + } + } + + return true; } -void SetupWizard::handlefinished() +void SetupWizard::handleFinished() { close(); AppConfig& appConfig = m_MainWindow.appConfig(); - appConfig.setWizardHasRun(true); + appConfig.setCryptoMode(parseCryptoMode(m_pComboCryptoMode->currentText())); + appConfig.setCryptoPass(m_pLineEditCryptoPass->text()); + + appConfig.setWizardHasRun(); appConfig.saveSettings(); QSettings& settings = m_MainWindow.settings(); @@ -95,6 +126,7 @@ void SetupWizard::handlefinished() settings.setValue("groupClientChecked", true); settings.setValue("groupServerChecked", false); } + settings.sync(); if (m_StartMain) @@ -102,3 +134,32 @@ void SetupWizard::handlefinished() m_MainWindow.start(true); } } + +void SetupWizard::on_m_pComboCryptoMode_currentIndexChanged(int index) +{ + bool enabled = parseCryptoMode(m_pComboCryptoMode->currentText()) != Disabled; + m_pLineEditCryptoPass->setEnabled(enabled); + m_pLineEditCryptoPassConfirm->setEnabled(enabled); +} + +CryptoMode SetupWizard::parseCryptoMode(const QString& s) +{ + if (s.startsWith("OFB")) + { + return OFB; + } + else if (s.startsWith("CFB")) + { + return CFB; + } + else if (s.startsWith("CTR")) + { + return CTR; + } + else if (s.startsWith("GCM")) + { + return GCM; + } + + return Disabled; +} diff --git a/src/gui/src/SetupWizard.h b/src/gui/src/SetupWizard.h index d2d8953d..6c0c79c8 100644 --- a/src/gui/src/SetupWizard.h +++ b/src/gui/src/SetupWizard.h @@ -18,8 +18,8 @@ #pragma once #include - #include "ui_SetupWizardBase.h" +#include "CryptoMode.h" class MainWindow; @@ -31,8 +31,11 @@ public: virtual ~SetupWizard(); bool validateCurrentPage(); protected slots: - void handlefinished(); + void handleFinished(); private: MainWindow& m_MainWindow; bool m_StartMain; + CryptoMode parseCryptoMode(const QString& s); +private slots: + void on_m_pComboCryptoMode_currentIndexChanged(int index); }; diff --git a/src/gui/src/main.cpp b/src/gui/src/main.cpp index 66bba88d..ee9bcb67 100644 --- a/src/gui/src/main.cpp +++ b/src/gui/src/main.cpp @@ -66,13 +66,13 @@ int main(int argc, char* argv[]) MainWindow mainWindow(settings, appConfig); SetupWizard setupWizard(mainWindow, true); - if (appConfig.wizardHasRun()) + if (appConfig.wizardShouldRun()) { - mainWindow.start(false); + setupWizard.show(); } else { - setupWizard.show(); + mainWindow.start(false); } return app.exec();