From 32bd271edf9bc6e6b757df3598550b33ca45d937 Mon Sep 17 00:00:00 2001 From: Jamie Newbon Date: Mon, 27 Jul 2020 17:21:46 +0100 Subject: [PATCH] #6669 Added TLS config options to select key length and certificate path Signed-off-by: Jamie Newbon --- src/gui/src/AppConfig.cpp | 25 ++++ src/gui/src/AppConfig.h | 25 ++++ src/gui/src/MainWindow.cpp | 4 - src/gui/src/SettingsDialog.cpp | 32 +++++ src/gui/src/SettingsDialog.h | 4 + src/gui/src/SettingsDialogBase.ui | 193 ++++++++++++++++++++++-------- src/gui/src/SslCertificate.cpp | 13 +- src/gui/src/SslCertificate.h | 6 +- 8 files changed, 244 insertions(+), 58 deletions(-) diff --git a/src/gui/src/AppConfig.cpp b/src/gui/src/AppConfig.cpp index 9904050780..dab12f894a 100644 --- a/src/gui/src/AppConfig.cpp +++ b/src/gui/src/AppConfig.cpp @@ -73,6 +73,8 @@ const char* AppConfig::m_SynergySettingsName[] = { "useInternalConfig", "groupClientChecked", "serverHostname", + "tlsCertPath", + "tlsKeyLength", }; static const char* logLevelNames[] = @@ -249,6 +251,13 @@ void AppConfig::loadSettings() m_ClientGroupChecked = loadSetting(kGroupClientCheck, true).toBool(); m_ServerHostname = loadSetting(kServerHostname).toString(); + //Set the default path of the TLS certificate file in the users DIR + QString certificateFilename = QString("%1/%2/%3").arg(m_CoreInterface.getProfileDir(), + "SSL", + "Synergy.pem"); + + m_TLSCertificatePath = loadSetting(kTLSCertPath, certificateFilename).toString(); + m_TLSKeyLength = loadSetting(kTLSKeyLength, 2048).toInt(); } @@ -527,3 +536,19 @@ void AppConfig::setSettingModified(T &variable, const T& newValue) { } } +void AppConfig::setTLSCertPath(const QString& path) { + m_TLSCertificatePath = path; +} + +QString AppConfig::getTLSCertPath() const { + return m_TLSCertificatePath; +} + +QString AppConfig::getTLSKeyLength() const { + return m_TLSKeyLength; +} + +void AppConfig::setTLSKeyLength(const QString& length) { + m_TLSKeyLength = length; +} + diff --git a/src/gui/src/AppConfig.h b/src/gui/src/AppConfig.h index 452899484d..0f40a70491 100644 --- a/src/gui/src/AppConfig.h +++ b/src/gui/src/AppConfig.h @@ -27,6 +27,7 @@ #include #include #include "ConfigBase.h" +#include "CoreInterface.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 @@ -126,6 +127,14 @@ class AppConfig: public QObject, public GUI::Config::ConfigBase bool getClientGroupChecked() const; QString getServerHostname() const; + /// @brief Gets the current TLS certificate path + /// @return QString The path to the cert + QString getTLSCertPath() const; + + /// @brief Get the key length to be used for the private key of a TLS cert + /// @return QString The key length in bits + QString getTLSKeyLength() const; + void setServerGroupChecked(bool); void setUseExternalConfig(bool) ; void setConfigFile(const QString&); @@ -133,6 +142,15 @@ class AppConfig: public QObject, public GUI::Config::ConfigBase void setClientGroupChecked(bool) ; void setServerHostname(const QString&); + /// @brief Set the path to the TLS/SSL certificate file that will be used + /// @param [in] path The path to the Certificate + void setTLSCertPath(const QString& path); + + /// @brief Sets the key length of the private key to use in a TLS connection + /// @param [in] QString length The key length eg: 1024, 2048, 4096 + void setTLSKeyLength(const QString& length); + + QString lastVersion() const; void setMinimizeToTray(bool b); @@ -174,6 +192,8 @@ protected: kUseInternalConfig, kGroupClientCheck, kServerHostname, + kTLSCertPath, + kTLSKeyLength, }; void setScreenName(const QString& s); @@ -224,10 +244,15 @@ protected: bool m_ClientGroupChecked; QString m_ServerHostname; + QString m_TLSCertificatePath; /// @brief The path to the TLS certificate file + QString m_TLSKeyLength; /// @brief The key length of the TLS cert to make + bool m_LoadFromSystemScope; /// @brief should the setting be loaded from SystemScope /// If the user has settings but this is true then /// system settings will be loaded instead of the users + CoreInterface m_CoreInterface; + static const char m_SynergysName[]; static const char m_SynergycName[]; static const char m_SynergyLogDir[]; diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 9b4da2b5df..72b715f14d 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -744,10 +744,6 @@ void MainWindow::retryStart() void MainWindow::sslToggled (bool enabled) { - if (enabled) { - m_pSslCertificate = new SslCertificate(this); - m_pSslCertificate->generateCertificate(); - } updateLocalFingerprint(); } diff --git a/src/gui/src/SettingsDialog.cpp b/src/gui/src/SettingsDialog.cpp index b8c720ec08..3965b56a4d 100644 --- a/src/gui/src/SettingsDialog.cpp +++ b/src/gui/src/SettingsDialog.cpp @@ -65,9 +65,22 @@ void SettingsDialog::accept() appConfig().setAutoHide(m_pCheckBoxAutoHide->isChecked()); appConfig().setAutoConfig(m_pCheckBoxAutoConfig->isChecked()); appConfig().setMinimizeToTray(m_pCheckBoxMinimizeToTray->isChecked()); + appConfig().setTLSCertPath(m_pLineEditCertificatePath->text()); + + bool keyLengthChanged = appConfig().getTLSKeyLength() != m_pComboBoxKeyLength->currentText(); + appConfig().setTLSKeyLength(m_pComboBoxKeyLength->currentText()); //We only need to test the System scoped Radio as they are connected appConfig().setLoadFromSystemScope(m_pRadioSystemScope->isChecked()); + + if(m_pCheckBoxEnableCrypto->isChecked()) { + SslCertificate sslCertificate; + sslCertificate.generateCertificate(appConfig().getTLSCertPath(), + m_pComboBoxKeyLength->currentText(), + keyLengthChanged); + } + m_appConfig.setCryptoEnabled(m_pCheckBoxEnableCrypto->isChecked()); + QDialog::accept(); } @@ -116,6 +129,8 @@ void SettingsDialog::loadFromConfig() { m_pCheckBoxAutoHide->setChecked(appConfig().getAutoHide()); m_pCheckBoxMinimizeToTray->setChecked(appConfig().getMinimizeToTray()); m_pCheckBoxEnableCrypto->setChecked(m_appConfig.getCryptoEnabled()); + m_pLineEditCertificatePath->setText(appConfig().getTLSCertPath()); + m_pComboBoxKeyLength->setCurrentIndex(m_pComboBoxKeyLength->findText(appConfig().getTLSKeyLength())); if (m_appConfig.isSystemScoped()) { m_pRadioSystemScope->setChecked(true); @@ -204,7 +219,11 @@ void SettingsDialog::on_m_pCheckBoxEnableCrypto_toggled(bool checked) SslCertificate sslCertificate; sslCertificate.generateCertificate(); m_pMainWindow->updateLocalFingerprint(); + verticalSpacer_4->changeSize(10, 10, QSizePolicy::Minimum); + } else { + verticalSpacer_4->changeSize(10, 0, QSizePolicy::Ignored); } + adjustSize(); } void SettingsDialog::on_m_pLabelInstallBonjour_linkActivated(const QString&) @@ -219,3 +238,16 @@ void SettingsDialog::on_m_pRadioSystemScope_toggled(bool checked) appConfig().setLoadFromSystemScope(checked); loadFromConfig(); } + +void SettingsDialog::on_m_pPushButtonBrowseCert_clicked() { + QString fileName = QFileDialog::getSaveFileName( + this, tr("Select a TLS certificate to use..."), + m_pLineEditCertificatePath->text(), + "Cert (*.pem)", + nullptr, + QFileDialog::DontConfirmOverwrite); + + if (!fileName.isEmpty()) { + m_pLineEditCertificatePath->setText(fileName); + } +} diff --git a/src/gui/src/SettingsDialog.h b/src/gui/src/SettingsDialog.h index 64596dda5c..d0b36df171 100644 --- a/src/gui/src/SettingsDialog.h +++ b/src/gui/src/SettingsDialog.h @@ -65,6 +65,10 @@ class SettingsDialog : public QDialog, public Ui::SettingsDialogBase /// @brief Handles the toggling of the system scoped radio button /// As the user scope radio is connected this will fire for either radio button void on_m_pRadioSystemScope_toggled(bool checked); + + /// @brief Handles the click event of the Cert Path browse button + /// displaying a file browser + void on_m_pPushButtonBrowseCert_clicked(); }; #endif diff --git a/src/gui/src/SettingsDialogBase.ui b/src/gui/src/SettingsDialogBase.ui index ef7fcc806f..7b240536cf 100644 --- a/src/gui/src/SettingsDialogBase.ui +++ b/src/gui/src/SettingsDialogBase.ui @@ -6,16 +6,15 @@ 0 0 - 357 - 496 + 378 + 756 Settings - - - + + &Settings Scope @@ -41,7 +40,7 @@ - + &Miscellaneous @@ -190,7 +189,7 @@ - + Qt::Vertical @@ -206,7 +205,7 @@ - + true @@ -220,10 +219,7 @@ &Network - - - QFormLayout::AllNonFixedFieldsGrow - + 2 @@ -236,7 +232,7 @@ 12 - + 0 @@ -244,36 +240,6 @@ 12 - - - - false - - - Enable &TLS Encryption - - - - - - - false - - - Enable Auto Config - - - - - - - <html><head/><body><p><a href="#"><span style=" text-decoration: underline; color:#007af4;">Install Bonjour</span></a></p></body></html> - - - Qt::RichText - - - @@ -287,12 +253,42 @@ + + + + <html><head/><body><p><a href="#"><span style=" text-decoration: underline; color:#007af4;">Install Bonjour</span></a></p></body></html> + + + Qt::RichText + + + + + + + false + + + Enable Auto Config + + + + + + + false + + + Enable &TLS Encryption + + + - + Qt::Vertical @@ -308,7 +304,85 @@ - + + + + TLS/SSL Settings + + + + + + + + + Key length + + + + + + + Certificate Path + + + + + + + Browse + + + + + + + 2048 + + + + 1024 + + + + + 2048 + + + + + 4096 + + + + + + + + Regenerate Cert + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Minimum + + + + 20 + 10 + + + + + @@ -393,7 +467,7 @@ - + Qt::Vertical @@ -409,7 +483,7 @@ - + Qt::Horizontal @@ -422,13 +496,20 @@ + m_pRadioSystemScope + m_pRadioUserScope m_pComboLanguage m_pLineEditScreenName m_pSpinBoxPort m_pLineEditInterface - m_pCheckBoxMinimizeToTray m_pComboElevate m_pCheckBoxAutoHide + m_pCheckBoxMinimizeToTray + m_pCheckBoxAutoConfig + m_pCheckBoxEnableCrypto + m_pComboBoxKeyLength + m_pLineEditCertificatePath + m_pPushButtonBrowseCert m_pComboLogLevel m_pCheckBoxLogToFile m_pLineEditLogFilename @@ -468,5 +549,21 @@ + + m_pCheckBoxEnableCrypto + toggled(bool) + m_pGroupBoxTLS + setVisible(bool) + + + 100 + 413 + + + 188 + 508 + + + diff --git a/src/gui/src/SslCertificate.cpp b/src/gui/src/SslCertificate.cpp index 777d4fd417..8a569567ef 100644 --- a/src/gui/src/SslCertificate.cpp +++ b/src/gui/src/SslCertificate.cpp @@ -25,7 +25,7 @@ -static const char kCertificateKeyLength[] = "rsa:2048"; //RSA Bit length (e.g. 1024/2048/4096) +static const char kCertificateKeyLength[] = "rsa:"; //RSA Bit length (e.g. 1024/2048/4096) static const char kCertificateHashAlgorithm[] = "-sha256"; //fingerprint hashing algorithm static const char kCertificateLifetime[] = "365"; static const char kCertificateSubjectInfo[] = "/CN=Synergy"; @@ -93,7 +93,7 @@ bool SslCertificate::runTool(const QStringList& args) return true; } -void SslCertificate::generateCertificate() +void SslCertificate::generateCertificate(const QString& path, const QString& keyLength, bool forceGen) { QString sslDirPath = QString("%1%2%3") .arg(m_ProfileDir) @@ -105,8 +105,11 @@ void SslCertificate::generateCertificate() .arg(QDir::separator()) .arg(kCertificateFilename); - QFile file(filename); - if (!file.exists()) { + QString keySize = kCertificateKeyLength + keyLength; + + //If path is empty use filename + QFile file(path.isEmpty() ? filename : path); + if (!file.exists() || forceGen) { QStringList arguments; // self signed certificate @@ -126,7 +129,7 @@ void SslCertificate::generateCertificate() // private key arguments.append("-newkey"); - arguments.append(kCertificateKeyLength); + arguments.append(keySize); QDir sslDir(sslDirPath); if (!sslDir.exists()) { diff --git a/src/gui/src/SslCertificate.h b/src/gui/src/SslCertificate.h index 6683269dfc..968f65b693 100644 --- a/src/gui/src/SslCertificate.h +++ b/src/gui/src/SslCertificate.h @@ -29,7 +29,11 @@ public: explicit SslCertificate(QObject *parent = 0); public slots: - void generateCertificate(); + /// @brief Generates a TLS cert and private key + /// @param [in] QString path The path of the file to be generated + /// @param [in] QString keyLength The size of the private key. default: 2048 + /// @param [in] bool Should the file be created regardless of if the file already exists + void generateCertificate(const QString& path = QString(), const QString& keyLength = "2048", bool forceGen = false); signals: void error(QString e);