diff options
Diffstat (limited to 'utils')
-rw-r--r-- | utils/rbutilqt/base/httpget.cpp | 23 | ||||
-rw-r--r-- | utils/rbutilqt/base/httpget.h | 5 | ||||
-rw-r--r-- | utils/rbutilqt/rbutilqt.cpp | 42 | ||||
-rw-r--r-- | utils/rbutilqt/rbutilqt.h | 1 |
4 files changed, 70 insertions, 1 deletions
diff --git a/utils/rbutilqt/base/httpget.cpp b/utils/rbutilqt/base/httpget.cpp index fb74514e73..0cd9236209 100644 --- a/utils/rbutilqt/base/httpget.cpp +++ b/utils/rbutilqt/base/httpget.cpp | |||
@@ -20,6 +20,7 @@ | |||
20 | 20 | ||
21 | #include <QNetworkAccessManager> | 21 | #include <QNetworkAccessManager> |
22 | #include <QNetworkRequest> | 22 | #include <QNetworkRequest> |
23 | #include <QSslConfiguration> | ||
23 | 24 | ||
24 | #include "httpget.h" | 25 | #include "httpget.h" |
25 | #include "Logger.h" | 26 | #include "Logger.h" |
@@ -27,6 +28,7 @@ | |||
27 | QString HttpGet::m_globalUserAgent; //< globally set user agent for requests | 28 | QString HttpGet::m_globalUserAgent; //< globally set user agent for requests |
28 | QDir HttpGet::m_globalCache; //< global cach path value for new objects | 29 | QDir HttpGet::m_globalCache; //< global cach path value for new objects |
29 | QNetworkProxy HttpGet::m_globalProxy; | 30 | QNetworkProxy HttpGet::m_globalProxy; |
31 | QList<QSslCertificate> HttpGet::m_acceptedClientCerts; | ||
30 | 32 | ||
31 | HttpGet::HttpGet(QObject *parent) | 33 | HttpGet::HttpGet(QObject *parent) |
32 | : QObject(parent), | 34 | : QObject(parent), |
@@ -211,9 +213,30 @@ void HttpGet::startRequest(QUrl url) | |||
211 | connect(m_reply, &QNetworkReply::errorOccurred, this, &HttpGet::networkError); | 213 | connect(m_reply, &QNetworkReply::errorOccurred, this, &HttpGet::networkError); |
212 | #endif | 214 | #endif |
213 | connect(m_reply, &QNetworkReply::downloadProgress, this, &HttpGet::downloadProgress); | 215 | connect(m_reply, &QNetworkReply::downloadProgress, this, &HttpGet::downloadProgress); |
216 | connect(m_reply, &QNetworkReply::sslErrors, this, &HttpGet::gotSslError); | ||
214 | } | 217 | } |
215 | 218 | ||
216 | 219 | ||
220 | void HttpGet::gotSslError(const QList<QSslError> &errors) | ||
221 | { | ||
222 | LOG_WARNING() << "Got SSL error" << errors; | ||
223 | |||
224 | // if this is a cert error, and only if we already accepted a remote cert | ||
225 | // ignore the error. | ||
226 | // This will make QNAM continue the request and finish it. | ||
227 | if (errors.size() == 1 | ||
228 | && errors.at(0).error() == QSslError::UnableToGetLocalIssuerCertificate | ||
229 | && m_acceptedClientCerts.contains(m_reply->sslConfiguration().peerCertificate())) { | ||
230 | LOG_INFO() << "client cert temporarily trusted by user."; | ||
231 | m_reply->ignoreSslErrors(); | ||
232 | } | ||
233 | else { | ||
234 | LOG_ERROR() << m_reply->sslConfiguration().peerCertificate().toText(); | ||
235 | emit sslError(errors.at(0), m_reply->sslConfiguration().peerCertificate()); | ||
236 | } | ||
237 | |||
238 | } | ||
239 | |||
217 | void HttpGet::networkError(QNetworkReply::NetworkError error) | 240 | void HttpGet::networkError(QNetworkReply::NetworkError error) |
218 | { | 241 | { |
219 | LOG_ERROR() << "NetworkError occured:" << error << m_reply->errorString(); | 242 | LOG_ERROR() << "NetworkError occured:" << error << m_reply->errorString(); |
diff --git a/utils/rbutilqt/base/httpget.h b/utils/rbutilqt/base/httpget.h index 443a606e6d..fb5b920b47 100644 --- a/utils/rbutilqt/base/httpget.h +++ b/utils/rbutilqt/base/httpget.h | |||
@@ -73,6 +73,8 @@ class HttpGet : public QObject | |||
73 | //< set global user agent string | 73 | //< set global user agent string |
74 | static void setGlobalUserAgent(const QString& u) | 74 | static void setGlobalUserAgent(const QString& u) |
75 | { m_globalUserAgent = u; } | 75 | { m_globalUserAgent = u; } |
76 | static void addTrustedPeerCert(QSslCertificate cert) | ||
77 | { m_acceptedClientCerts.append(cert);} | ||
76 | 78 | ||
77 | public slots: | 79 | public slots: |
78 | void abort(void); | 80 | void abort(void); |
@@ -81,14 +83,17 @@ class HttpGet : public QObject | |||
81 | void done(QNetworkReply::NetworkError error); | 83 | void done(QNetworkReply::NetworkError error); |
82 | void dataReadProgress(int, int); | 84 | void dataReadProgress(int, int); |
83 | void headerFinished(void); | 85 | void headerFinished(void); |
86 | void sslError(const QSslError& error, const QSslCertificate& peerCert); | ||
84 | 87 | ||
85 | private slots: | 88 | private slots: |
86 | void requestFinished(QNetworkReply* reply); | 89 | void requestFinished(QNetworkReply* reply); |
87 | void startRequest(QUrl url); | 90 | void startRequest(QUrl url); |
88 | void downloadProgress(qint64 received, qint64 total); | 91 | void downloadProgress(qint64 received, qint64 total); |
89 | void networkError(QNetworkReply::NetworkError error); | 92 | void networkError(QNetworkReply::NetworkError error); |
93 | void gotSslError(const QList<QSslError> &errors); | ||
90 | 94 | ||
91 | private: | 95 | private: |
96 | static QList<QSslCertificate> m_acceptedClientCerts; | ||
92 | static QString m_globalUserAgent; | 97 | static QString m_globalUserAgent; |
93 | static QNetworkProxy m_globalProxy; | 98 | static QNetworkProxy m_globalProxy; |
94 | QNetworkAccessManager m_mgr; | 99 | QNetworkAccessManager m_mgr; |
diff --git a/utils/rbutilqt/rbutilqt.cpp b/utils/rbutilqt/rbutilqt.cpp index 6d0da3390f..680303859e 100644 --- a/utils/rbutilqt/rbutilqt.cpp +++ b/utils/rbutilqt/rbutilqt.cpp | |||
@@ -205,6 +205,7 @@ void RbUtilQt::downloadInfo() | |||
205 | // try to get the current build information | 205 | // try to get the current build information |
206 | daily = new HttpGet(this); | 206 | daily = new HttpGet(this); |
207 | connect(daily, &HttpGet::done, this, &RbUtilQt::downloadDone); | 207 | connect(daily, &HttpGet::done, this, &RbUtilQt::downloadDone); |
208 | connect(daily, &HttpGet::sslError, this, &RbUtilQt::sslError); | ||
208 | connect(qApp, &QGuiApplication::lastWindowClosed, daily, &HttpGet::abort); | 209 | connect(qApp, &QGuiApplication::lastWindowClosed, daily, &HttpGet::abort); |
209 | daily->setCache(false); | 210 | daily->setCache(false); |
210 | ui.statusbar->showMessage(tr("Downloading build information, please wait ...")); | 211 | ui.statusbar->showMessage(tr("Downloading build information, please wait ...")); |
@@ -213,10 +214,49 @@ void RbUtilQt::downloadInfo() | |||
213 | daily->getFile(QUrl(PlayerBuildInfo::instance()->value(PlayerBuildInfo::BuildInfoUrl).toString())); | 214 | daily->getFile(QUrl(PlayerBuildInfo::instance()->value(PlayerBuildInfo::BuildInfoUrl).toString())); |
214 | } | 215 | } |
215 | 216 | ||
217 | void RbUtilQt::sslError(const QSslError& error, const QSslCertificate& peerCert) | ||
218 | { | ||
219 | LOG_WARNING() << "sslError" << (int)error.error(); | ||
220 | // On Rockbox Utility start we always try to get the build info first. | ||
221 | // Thus we can use that to catch potential certificate errors. | ||
222 | // If the user accepts the certificate we'll have HttpGet ignore all cert | ||
223 | // errors for the exact certificate we got during this first request. | ||
224 | // Thus we don't need to handle cert errors later anymore. | ||
225 | if (error.error() == QSslError::UnableToGetLocalIssuerCertificate) { | ||
226 | QMessageBox mb(this); | ||
227 | mb.setWindowTitle(tr("Certificate error")); | ||
228 | mb.setIcon(QMessageBox::Warning); | ||
229 | mb.setText(tr("%1\n\n" | ||
230 | "Issuer: %2\n" | ||
231 | "Subject: %3\n" | ||
232 | "Valid since: %4\n" | ||
233 | "Valid until: %5\n\n" | ||
234 | "Temporarily trust certificate?") | ||
235 | .arg(error.errorString()) | ||
236 | .arg(peerCert.issuerInfo(QSslCertificate::Organization).at(0)) | ||
237 | .arg(peerCert.subjectDisplayName()) | ||
238 | .arg(peerCert.effectiveDate().toString()) | ||
239 | .arg(peerCert.expiryDate().toString()) | ||
240 | ); | ||
241 | mb.setDetailedText(peerCert.toText()); | ||
242 | mb.setStandardButtons(QMessageBox::Yes | QMessageBox::No); | ||
243 | |||
244 | auto r = mb.exec(); | ||
245 | if (r == QMessageBox::Yes) { | ||
246 | HttpGet::addTrustedPeerCert(peerCert); | ||
247 | downloadInfo(); | ||
248 | } | ||
249 | else { | ||
250 | downloadDone(QNetworkReply::OperationCanceledError); | ||
251 | } | ||
252 | } | ||
253 | } | ||
254 | |||
216 | 255 | ||
217 | void RbUtilQt::downloadDone(QNetworkReply::NetworkError error) | 256 | void RbUtilQt::downloadDone(QNetworkReply::NetworkError error) |
218 | { | 257 | { |
219 | if(error != QNetworkReply::NoError) { | 258 | if(error != QNetworkReply::NoError |
259 | && error != QNetworkReply::SslHandshakeFailedError) { | ||
220 | LOG_INFO() << "network error:" << daily->errorString(); | 260 | LOG_INFO() << "network error:" << daily->errorString(); |
221 | ui.statusbar->showMessage(tr("Can't get version information!")); | 261 | ui.statusbar->showMessage(tr("Can't get version information!")); |
222 | QMessageBox::critical(this, tr("Network error"), | 262 | QMessageBox::critical(this, tr("Network error"), |
diff --git a/utils/rbutilqt/rbutilqt.h b/utils/rbutilqt/rbutilqt.h index c507317fa2..9caa8a1267 100644 --- a/utils/rbutilqt/rbutilqt.h +++ b/utils/rbutilqt/rbutilqt.h | |||
@@ -72,6 +72,7 @@ class RbUtilQt : public QMainWindow | |||
72 | bool m_auto; | 72 | bool m_auto; |
73 | 73 | ||
74 | private slots: | 74 | private slots: |
75 | void sslError(const QSslError& error, const QSslCertificate& peerCert); | ||
75 | void shutdown(void); | 76 | void shutdown(void); |
76 | void about(void); | 77 | void about(void); |
77 | void help(void); | 78 | void help(void); |