From 759bf4d73de407776c8b0734d841719e60cb7922 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Thu, 16 Feb 2017 16:57:48 +0800 Subject: [PATCH] Allow to load/use ECDSA certificate in webUI. Limit max read size Improve messages in dialogs Refactor --- src/gui/optionsdlg.cpp | 59 +++++++++++++++++++++++------------------- src/gui/optionsdlg.h | 4 +-- src/webui/webui.cpp | 21 +++++++++------ 3 files changed, 48 insertions(+), 36 deletions(-) diff --git a/src/gui/optionsdlg.cpp b/src/gui/optionsdlg.cpp index ce82dc750..1b52c501f 100644 --- a/src/gui/optionsdlg.cpp +++ b/src/gui/optionsdlg.cpp @@ -978,8 +978,8 @@ void OptionsDialog::loadOptions() m_ui->spinWebUiPort->setValue(pref->getWebUiPort()); m_ui->checkWebUIUPnP->setChecked(pref->useUPnPForWebUIPort()); m_ui->checkWebUiHttps->setChecked(pref->isWebUiHttpsEnabled()); - setSslCertificate(pref->getWebUiHttpsCertificate(), false); - setSslKey(pref->getWebUiHttpsKey(), false); + setSslCertificate(pref->getWebUiHttpsCertificate()); + setSslKey(pref->getWebUiHttpsKey()); m_ui->textWebUiUsername->setText(pref->getWebUiUsername()); m_ui->textWebUiPassword->setText(pref->getWebUiPassword()); m_ui->checkBypassLocalAuth->setChecked(!pref->isWebUiLocalAuthEnabled()); @@ -1511,26 +1511,32 @@ void OptionsDialog::showConnectionTab() void OptionsDialog::on_btnWebUiCrt_clicked() { - QString filename = QFileDialog::getOpenFileName(this, QString(), QString(), tr("SSL Certificate") + QString(" (*.crt *.pem)")); - if (filename.isNull()) + const QString filename = QFileDialog::getOpenFileName(this, tr("Import SSL certificate"), QString(), tr("SSL Certificate") + QLatin1String(" (*.crt *.pem)")); + if (filename.isEmpty()) return; - QFile file(filename); - if (file.open(QIODevice::ReadOnly)) { - setSslCertificate(file.readAll()); - file.close(); - } + + QFile cert(filename); + if (!cert.open(QIODevice::ReadOnly)) + return; + + bool success = setSslCertificate(cert.read(1024 * 1024)); + if (!success) + QMessageBox::warning(this, tr("Invalid certificate"), tr("This is not a valid SSL certificate.")); } void OptionsDialog::on_btnWebUiKey_clicked() { - QString filename = QFileDialog::getOpenFileName(this, QString(), QString(), tr("SSL Key") + QString(" (*.key *.pem)")); - if (filename.isNull()) + const QString filename = QFileDialog::getOpenFileName(this, tr("Import SSL key"), QString(), tr("SSL key") + QLatin1String(" (*.key *.pem)")); + if (filename.isEmpty()) return; - QFile file(filename); - if (file.open(QIODevice::ReadOnly)) { - setSslKey(file.readAll()); - file.close(); - } + + QFile key(filename); + if (!key.open(QIODevice::ReadOnly)) + return; + + bool success = setSslKey(key.read(1024 * 1024)); + if (!success) + QMessageBox::warning(this, tr("Invalid key"), tr("This is not a valid SSL key.")); } void OptionsDialog::on_registerDNSBtn_clicked() @@ -1638,41 +1644,42 @@ QString OptionsDialog::languageToLocalizedString(const QLocale &locale) } } -void OptionsDialog::setSslKey(const QByteArray &key, bool interactive) +bool OptionsDialog::setSslKey(const QByteArray &key) { #ifndef QT_NO_OPENSSL - if (!key.isEmpty() && !QSslKey(key, QSsl::Rsa).isNull()) { + // try different formats + const bool isKeyValid = (!QSslKey(key, QSsl::Rsa).isNull() || !QSslKey(key, QSsl::Ec).isNull()); + if (isKeyValid) { m_ui->lblSslKeyStatus->setPixmap(QPixmap(":/icons/qbt-theme/security-high.png").scaledToHeight(20, Qt::SmoothTransformation)); m_sslKey = key; } else { m_ui->lblSslKeyStatus->setPixmap(QPixmap(":/icons/qbt-theme/security-low.png").scaledToHeight(20, Qt::SmoothTransformation)); m_sslKey.clear(); - if (interactive) - QMessageBox::warning(this, tr("Invalid key"), tr("This is not a valid SSL key.")); } + return isKeyValid; #else Q_UNUSED(key); - Q_UNUSED(interactive); + return false; #endif } -void OptionsDialog::setSslCertificate(const QByteArray &cert, bool interactive) +bool OptionsDialog::setSslCertificate(const QByteArray &cert) { #ifndef QT_NO_OPENSSL - if (!cert.isEmpty() && !QSslCertificate(cert).isNull()) { + const bool isCertValid = !QSslCertificate(cert).isNull(); + if (isCertValid) { m_ui->lblSslCertStatus->setPixmap(QPixmap(":/icons/qbt-theme/security-high.png").scaledToHeight(20, Qt::SmoothTransformation)); m_sslCert = cert; } else { m_ui->lblSslCertStatus->setPixmap(QPixmap(":/icons/qbt-theme/security-low.png").scaledToHeight(20, Qt::SmoothTransformation)); m_sslCert.clear(); - if (interactive) - QMessageBox::warning(this, tr("Invalid certificate"), tr("This is not a valid SSL certificate.")); } + return isCertValid; #else Q_UNUSED(cert); - Q_UNUSED(interactive); + return false; #endif } diff --git a/src/gui/optionsdlg.h b/src/gui/optionsdlg.h index 061b2863e..01fb0fab5 100644 --- a/src/gui/optionsdlg.h +++ b/src/gui/optionsdlg.h @@ -171,8 +171,8 @@ private: QSize sizeFittingScreen() const; private: - void setSslKey(const QByteArray &key, bool interactive = true); - void setSslCertificate(const QByteArray &cert, bool interactive = true); + bool setSslKey(const QByteArray &key); + bool setSslCertificate(const QByteArray &cert); bool schedTimesOk(); bool webUIAuthenticationOk(); diff --git a/src/webui/webui.cpp b/src/webui/webui.cpp index e4d5d62b1..7e0f2996a 100644 --- a/src/webui/webui.cpp +++ b/src/webui/webui.cpp @@ -26,13 +26,14 @@ * exception statement from your version. */ -#include "base/preferences.h" -#include "base/logger.h" +#include "webui.h" + #include "base/http/server.h" +#include "base/logger.h" #include "base/net/dnsupdater.h" #include "base/net/portforwarder.h" +#include "base/preferences.h" #include "webapplication.h" -#include "webui.h" WebUI::WebUI(QObject *parent) : QObject(parent) @@ -65,11 +66,15 @@ void WebUI::init() #ifndef QT_NO_OPENSSL if (pref->isWebUiHttpsEnabled()) { - QList certs = QSslCertificate::fromData(pref->getWebUiHttpsCertificate()); - QSslKey key; - key = QSslKey(pref->getWebUiHttpsKey(), QSsl::Rsa); - bool certsIsNull = std::any_of(certs.begin(), certs.end(), [](QSslCertificate c) { return c.isNull(); }); - if (!certsIsNull && !certs.empty() && !key.isNull()) + const QByteArray keyRaw = pref->getWebUiHttpsKey(); + QSslKey key(keyRaw, QSsl::Rsa); + if (key.isNull()) + key = QSslKey(keyRaw, QSsl::Ec); + + const QList certs = QSslCertificate::fromData(pref->getWebUiHttpsCertificate()); + const bool areCertsValid = !certs.empty() && std::all_of(certs.begin(), certs.end(), [](QSslCertificate c) { return !c.isNull(); }); + + if (!key.isNull() && areCertsValid) httpServer_->enableHttps(certs, key); else httpServer_->disableHttps();