1
mirror of https://invent.kde.org/network/falkon.git synced 2024-12-20 10:46:35 +01:00

NetworkManager: Fixed excessive questions about invalid SSL certificate

- user will now be asked only once if he rejects the certificate
   * works only within WebPage, so if user opens new tab, he will
     get the question again (in case he want to change his mind)
This commit is contained in:
nowrep 2012-07-03 15:22:42 +02:00
parent 193a9371f0
commit 8542dc307f
3 changed files with 93 additions and 34 deletions

View File

@ -145,28 +145,18 @@ void NetworkManager::setSSLConfiguration(QNetworkReply* reply)
} }
} }
inline uint qHash(const QSslCertificate &cert)
{
return qHash(cert.toPem());
}
void NetworkManager::sslError(QNetworkReply* reply, QList<QSslError> errors) void NetworkManager::sslError(QNetworkReply* reply, QList<QSslError> errors)
{ {
if (m_ignoreAllWarnings) { if (m_ignoreAllWarnings || reply->property("downReply").toBool()) {
reply->ignoreSslErrors(errors); reply->ignoreSslErrors(errors);
return; return;
} }
if (reply->property("downReply").toBool()) {
return;
}
int errorsIgnored = 0;
foreach(const QSslError & error, errors) {
if (m_ignoredCerts.contains(error.certificate())) {
++errorsIgnored;
}
}
if (errorsIgnored == errors.count()) {
return;
}
QNetworkRequest request = reply->request(); QNetworkRequest request = reply->request();
QVariant v = request.attribute((QNetworkRequest::Attribute)(QNetworkRequest::User + 100)); QVariant v = request.attribute((QNetworkRequest::Attribute)(QNetworkRequest::User + 100));
WebPage* webPage = static_cast<WebPage*>(v.value<void*>()); WebPage* webPage = static_cast<WebPage*>(v.value<void*>());
@ -174,43 +164,76 @@ void NetworkManager::sslError(QNetworkReply* reply, QList<QSslError> errors)
return; return;
} }
QHash<QSslCertificate, QStringList> errorHash;
foreach(const QSslError & error, errors) {
// Weird behavior on Windows
if (error.error() == QSslError::NoError) {
continue;
}
const QSslCertificate &cert = error.certificate();
if (errorHash.contains(cert)) {
errorHash[cert].append(error.errorString());
}
else {
errorHash.insert(cert, QStringList(error.errorString()));
}
}
// User already rejected those certs on this page
if (webPage->containsRejectedCerts(errorHash.keys())) {
return;
}
QString title = tr("SSL Certificate Error!"); QString title = tr("SSL Certificate Error!");
QString text1 = tr("The page you are trying to access has the following errors in the SSL certificate:"); QString text1 = tr("The page you are trying to access has the following errors in the SSL certificate:");
QString certs; QString certs;
foreach(const QSslError & error, errors) { QHash<QSslCertificate, QStringList>::const_iterator i = errorHash.constBegin();
if (m_localCerts.contains(error.certificate())) { while (i != errorHash.constEnd()) {
continue; const QSslCertificate &cert = i.key();
} const QStringList &errors = i.value();
if (error.error() == QSslError::NoError) { //Weird behavior on Windows
if (m_localCerts.contains(cert) || errors.isEmpty()) {
++i;
continue; continue;
} }
QSslCertificate cert = error.certificate();
certs += "<ul><li>"; certs += "<ul><li>";
certs += tr("<b>Organization: </b>") + CertificateInfoWidget::clearCertSpecialSymbols(cert.subjectInfo(QSslCertificate::Organization)); certs += tr("<b>Organization: </b>") + CertificateInfoWidget::clearCertSpecialSymbols(cert.subjectInfo(QSslCertificate::Organization));
certs += "</li><li>"; certs += "</li><li>";
certs += tr("<b>Domain Name: </b>") + CertificateInfoWidget::clearCertSpecialSymbols(cert.subjectInfo(QSslCertificate::CommonName)); certs += tr("<b>Domain Name: </b>") + CertificateInfoWidget::clearCertSpecialSymbols(cert.subjectInfo(QSslCertificate::CommonName));
certs += "</li><li>"; certs += "</li><li>";
certs += tr("<b>Expiration Date: </b>") + cert.expiryDate().toString("hh:mm:ss dddd d. MMMM yyyy"); certs += tr("<b>Expiration Date: </b>") + cert.expiryDate().toString("hh:mm:ss dddd d. MMMM yyyy");
certs += "</li><li>";
certs += tr("<b>Error: </b>") + error.errorString();
certs += "</li></ul>"; certs += "</li></ul>";
certs += "<ul>";
foreach(const QString & error, errors) {
certs += "<li>";
certs += tr("<b>Error: </b>") + error;
certs += "</li>";
}
certs += "</ul>";
++i;
} }
QString text2 = tr("Would you like to make an exception for this certificate?"); QString text2 = tr("Would you like to make an exception for this certificate?");
QString message = QString("<b>%1</b><p>%2</p>%3<p>%4</p>").arg(title, text1, certs, text2); QString message = QString("<b>%1</b><p>%2</p>%3<p>%4</p>").arg(title, text1, certs, text2);
if (!certs.isEmpty()) { if (!certs.isEmpty()) {
if (QMessageBox::critical(webPage->view(), tr("SSL Certificate Error!"), message, QMessageBox::StandardButton button = QMessageBox::critical(webPage->view(), tr("SSL Certificate Error!"), message, QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No) { if (button == QMessageBox::No) {
// To prevent asking user more than once for the same certificate
webPage->addRejectedCerts(errorHash.keys());
return; return;
} }
foreach(const QSslError & error, errors) { foreach(const QSslCertificate & cert, errorHash.keys()) {
if (!m_localCerts.contains(error.certificate())) { if (!m_localCerts.contains(cert)) {
addLocalCertificate(error.certificate()); addLocalCertificate(cert);
} }
} }
} }
@ -365,6 +388,7 @@ QNetworkReply* NetworkManager::createRequest(QNetworkAccessManager::Operation op
void NetworkManager::removeLocalCertificate(const QSslCertificate &cert) void NetworkManager::removeLocalCertificate(const QSslCertificate &cert)
{ {
m_localCerts.removeOne(cert); m_localCerts.removeOne(cert);
QList<QSslCertificate> certs = QSslSocket::defaultCaCertificates(); QList<QSslCertificate> certs = QSslSocket::defaultCaCertificates();
certs.removeOne(cert); certs.removeOne(cert);
QSslSocket::setDefaultCaCertificates(certs); QSslSocket::setDefaultCaCertificates(certs);

View File

@ -67,6 +67,7 @@ WebPage::WebPage(QupZilla* mainClass)
, m_speedDial(mApp->plugins()->speedDial()) , m_speedDial(mApp->plugins()->speedDial())
, m_fileWatcher(0) , m_fileWatcher(0)
, m_runningLoop(0) , m_runningLoop(0)
, m_loadProgress(-1)
, m_blockAlerts(false) , m_blockAlerts(false)
, m_secureStatus(false) , m_secureStatus(false)
, m_adjustingScheduled(false) , m_adjustingScheduled(false)
@ -142,11 +143,38 @@ bool WebPage::loadingError() const
return !mainFrame()->findFirstElement("span[id=\"qupzilla-error-page\"]").isNull(); return !mainFrame()->findFirstElement("span[id=\"qupzilla-error-page\"]").isNull();
} }
void WebPage::addRejectedCerts(const QList<QSslCertificate> &certs)
{
foreach(const QSslCertificate & cert, certs) {
if (!m_rejectedSslCerts.contains(cert)) {
m_rejectedSslCerts.append(cert);
}
}
}
bool WebPage::containsRejectedCerts(const QList<QSslCertificate> &certs) const
{
int matches = 0;
foreach(const QSslCertificate & cert, certs) {
if (m_rejectedSslCerts.contains(cert)) {
++matches;
}
}
return matches == certs.count();
}
bool WebPage::isRunningLoop() bool WebPage::isRunningLoop()
{ {
return m_runningLoop; return m_runningLoop;
} }
bool WebPage::isLoading() const
{
return m_loadProgress < 100;
}
void WebPage::setUserAgent(const QString &agent) void WebPage::setUserAgent(const QString &agent)
{ {
if (!agent.isEmpty()) { if (!agent.isEmpty()) {
@ -161,13 +189,15 @@ void WebPage::urlChanged(const QUrl &url)
{ {
Q_UNUSED(url) Q_UNUSED(url)
if (isLoading()) {
m_adBlockedEntries.clear(); m_adBlockedEntries.clear();
m_blockAlerts = false; m_blockAlerts = false;
} }
}
void WebPage::progress(int prog) void WebPage::progress(int prog)
{ {
Q_UNUSED(prog) m_loadProgress = prog;
bool secStatus = sslCertificate().isValid(); bool secStatus = sslCertificate().isValid();

View File

@ -67,8 +67,12 @@ public:
void scheduleAdjustPage(); void scheduleAdjustPage();
bool isRunningLoop(); bool isRunningLoop();
bool isLoading() const;
bool loadingError() const; bool loadingError() const;
void addRejectedCerts(const QList<QSslCertificate> &certs);
bool containsRejectedCerts(const QList<QSslCertificate> &certs) const;
static void setUserAgent(const QString &agent); static void setUserAgent(const QString &agent);
QString userAgentForUrl(const QUrl &url) const; QString userAgentForUrl(const QUrl &url) const;
@ -123,12 +127,13 @@ private:
TabbedWebView* m_view; TabbedWebView* m_view;
SpeedDial* m_speedDial; SpeedDial* m_speedDial;
QSslCertificate m_SslCert; QSslCertificate m_SslCert;
QList<QSslCertificate> m_SslCerts; QList<QSslCertificate> m_rejectedSslCerts;
QList<AdBlockedEntry> m_adBlockedEntries; QList<AdBlockedEntry> m_adBlockedEntries;
QFileSystemWatcher* m_fileWatcher; QFileSystemWatcher* m_fileWatcher;
QEventLoop* m_runningLoop; QEventLoop* m_runningLoop;
int m_loadProgress;
bool m_blockAlerts; bool m_blockAlerts;
bool m_secureStatus; bool m_secureStatus;
bool m_adjustingScheduled; bool m_adjustingScheduled;