From bae3b94fd6d53a52b519c429760be925d66690ab Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Sun, 4 Dec 2016 14:17:01 +0000 Subject: [PATCH] Build a cache of allowed SSL exceptions and use them on future network requests The class NetworkAccessManager sub-classes QNetworkAccessManager adding a message box to ask the user if SSL errors may be ignored. Ignored errors are ignored in future server replies so that the user is not asked about he same peer certificate chain repeatedly. The cache is currently per process only and not persistent. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@7361 ab8295b8-cf94-4d9e-aec4-7959e3be5d79 --- NetworkAccessManager.hpp | 63 ++++++++++++++++++++++++++++++++++++++++ main.cpp | 21 +------------- mainwindow.cpp | 12 ++++---- mainwindow.h | 4 +-- 4 files changed, 73 insertions(+), 27 deletions(-) create mode 100644 NetworkAccessManager.hpp diff --git a/NetworkAccessManager.hpp b/NetworkAccessManager.hpp new file mode 100644 index 000000000..2381621de --- /dev/null +++ b/NetworkAccessManager.hpp @@ -0,0 +1,63 @@ +#ifndef NETWORK_ACCESS_MANAGER_HPP__ +#define NETWORK_ACCESS_MANAGER_HPP__ + +#include +#include +#include +#include +#include + +#include "MessageBox.hpp" + +class QNetworkRequest; +class QIODevice; +class QWidget; + +// sub-class QNAM to keep a list of accepted SSL errors and allow +// them in future replies +class NetworkAccessManager + : public QNetworkAccessManager +{ +public: + NetworkAccessManager (QWidget * parent = nullptr) + : QNetworkAccessManager (parent) + { + // handle SSL errors that have not been cached as allowed + // exceptions and offer them to the user to add to the ignored + // exception cache + connect (this, &QNetworkAccessManager::sslErrors, [this, &parent] (QNetworkReply * reply, QList const& errors) { + QString message; + for (auto const& error: errors) + { + message += '\n' + reply->request ().url ().toDisplayString () + ": " + + error.errorString (); + } + QString certs; + for (auto const& cert : reply->sslConfiguration ().peerCertificateChain ()) + { + certs += cert.toText () + '\n'; + } + if (MessageBox::Ignore == MessageBox::query_message (parent, tr ("Network SSL Errors"), message, certs, MessageBox::Abort | MessageBox::Ignore)) + { + // accumulate SSL error exceptions that have been allowed + allowed_ssl_errors_.append (errors); + reply->ignoreSslErrors (errors); + } + }); + } + +protected: + QNetworkReply * createRequest (Operation operation, QNetworkRequest const& request, QIODevice * outgoing_data = nullptr) override + { + auto reply = QNetworkAccessManager::createRequest (operation, request, outgoing_data); + // errors are usually certificate specific so passing all cached + // exceptions here is ok + reply->ignoreSslErrors (allowed_ssl_errors_); + return reply; + } + +private: + QList allowed_ssl_errors_; +}; + +#endif diff --git a/main.cpp b/main.cpp index e1a415695..d5c5ab87b 100644 --- a/main.cpp +++ b/main.cpp @@ -8,8 +8,6 @@ #include #include -#include -#include #include #include #include @@ -316,25 +314,8 @@ int main(int argc, char *argv[]) ).toBool () ? 1u : 4u; } - QNetworkAccessManager network_manager {&a}; - // run the application UI - MainWindow w(temp_dir, multiple, &multi_settings, &mem_jt9, downSampleFactor, &network_manager, &splash); - - // set up handling for any SSL issues - QObject::connect (&network_manager, &QNetworkAccessManager::sslErrors, [&w] (QNetworkReply * reply, QList const& errors) { - QString message; - for (auto const& error: errors) - { - message += '\n' + reply->request ().url ().toDisplayString () + ": " - + error.errorString (); - } - if (QMessageBox::Ignore == QMessageBox::question (&w, "Network SSL Errors", message, QMessageBox::Abort | QMessageBox::Ignore)) - { - reply->ignoreSslErrors (); - } - }); - + MainWindow w(temp_dir, multiple, &multi_settings, &mem_jt9, downSampleFactor, &splash); w.show(); splash.raise (); QObject::connect (&a, SIGNAL (lastWindowClosed()), &a, SLOT (quit())); diff --git a/mainwindow.cpp b/mainwindow.cpp index 03f28947c..56d4413c2 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -26,6 +26,7 @@ #include "revision_utils.hpp" #include "qt_helpers.hpp" +#include "NetworkAccessManager.hpp" #include "soundout.h" #include "soundin.h" #include "Modulator.hpp" @@ -157,9 +158,10 @@ namespace //--------------------------------------------------- MainWindow constructor MainWindow::MainWindow(QDir const& temp_directory, bool multiple, MultiSettings * multi_settings, QSharedMemory *shdmem, - unsigned downSampleFactor, QNetworkAccessManager * network_manager, + unsigned downSampleFactor, QSplashScreen * splash, QWidget *parent) : QMainWindow(parent), + m_network_manager {this}, m_valid {true}, m_splash {splash}, m_dataDir {QStandardPaths::writableLocation (QStandardPaths::DataLocation)}, @@ -254,7 +256,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, m_onAirFreq0 {0.0}, m_first_error {true}, tx_status_label {"Receiving"}, - wsprNet {new WSPRNet {network_manager, this}}, + wsprNet {new WSPRNet {&m_network_manager, this}}, m_appDir {QApplication::applicationDirPath ()}, m_palette {"Linrad"}, m_mode {"JT9"}, @@ -336,7 +338,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, m_config.udp_server_name (), m_config.udp_server_port (), this}}, psk_Reporter {new PSK_Reporter {m_messageClient, this}}, - m_manual {network_manager} + m_manual {&m_network_manager} { ui->setupUi(this); createStatusBar(); @@ -485,10 +487,10 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, ui->actionMediumDecode->setActionGroup(DepthGroup); ui->actionDeepestDecode->setActionGroup(DepthGroup); - connect (ui->download_samples_action, &QAction::triggered, [this, network_manager] () { + connect (ui->download_samples_action, &QAction::triggered, [this] () { if (!m_sampleDownloader) { - m_sampleDownloader.reset (new SampleDownloader {m_settings, &m_config, network_manager, this}); + m_sampleDownloader.reset (new SampleDownloader {m_settings, &m_config, &m_network_manager, this}); } m_sampleDownloader->show (); }); diff --git a/mainwindow.h b/mainwindow.h index c43c740f7..c470e5f58 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -35,6 +35,7 @@ #include "commons.h" #include "astro.h" #include "MessageBox.hpp" +#include "NetworkAccessManager.hpp" #define NUM_JT4_SYMBOLS 206 //(72+31)*2, embedded sync #define NUM_JT65_SYMBOLS 126 //63 data + 63 sync @@ -55,7 +56,6 @@ namespace Ui { } class QSettings; -class QNetworkAccessManager; class QLineEdit; class QFont; class QHostInfo; @@ -88,7 +88,6 @@ public: explicit MainWindow(QDir const& temp_directory, bool multiple, MultiSettings *, QSharedMemory *shdmem, unsigned downSampleFactor, - QNetworkAccessManager * network_manager, QSplashScreen *, QWidget *parent = nullptr); ~MainWindow(); @@ -279,6 +278,7 @@ private: void astroUpdate (); void writeAllTxt(QString message); + NetworkAccessManager m_network_manager; bool m_valid; QSplashScreen * m_splash; QDir m_dataDir;