Auto-handle equal SSL errors for the same host.

For every (scheme, host, port) tuple, we save all SSL errors we asked the user
about, and if everything matches (scheme, host, port, error, certificate), we
don't ask the user again.

Fixes #422.
This commit is contained in:
Florian Bruhin 2015-03-10 07:58:40 +01:00
parent 8307b546b7
commit 2da45e98ca
2 changed files with 31 additions and 6 deletions

View File

@ -19,6 +19,8 @@
"""Our own QNetworkAccessManager."""
import collections
from PyQt5.QtCore import pyqtSlot, pyqtSignal, PYQT_VERSION, QCoreApplication
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkReply
@ -30,7 +32,8 @@ else:
SSL_AVAILABLE = QSslSocket.supportsSsl()
from qutebrowser.config import config
from qutebrowser.utils import message, log, usertypes, utils, objreg, qtutils
from qutebrowser.utils import (message, log, usertypes, utils, objreg, qtutils,
urlutils)
from qutebrowser.browser import cookies
from qutebrowser.browser.network import qutescheme, networkreply
@ -64,6 +67,8 @@ class NetworkManager(QNetworkAccessManager):
schemes.
_win_id: The window ID this NetworkManager is associated with.
_tab_id: The tab ID this NetworkManager is associated with.
_rejected_ssl_errors: A {QUrl: [QSslError]} dict of rejected errors.
_accepted_ssl_errors: A {QUrl: [QSslError]} dict of accepted errors.
Signals:
shutting_down: Emitted when the QNAM is shutting down.
@ -89,6 +94,8 @@ class NetworkManager(QNetworkAccessManager):
self._set_cache()
if SSL_AVAILABLE:
self.sslErrors.connect(self.on_ssl_errors)
self._rejected_ssl_errors = collections.defaultdict(list)
self._accepted_ssl_errors = collections.defaultdict(list)
self.authenticationRequired.connect(self.on_authentication_required)
self.proxyAuthenticationRequired.connect(
self.on_proxy_authentication_required)
@ -182,12 +189,22 @@ class NetworkManager(QNetworkAccessManager):
"""
ssl_strict = config.get('network', 'ssl-strict')
if ssl_strict == 'ask':
err_string = '\n'.join('- ' + err.errorString() for err in
errors)
answer = self._ask('SSL errors - continue?\n{}'.format(
err_string), mode=usertypes.PromptMode.yesno, owner=reply)
if answer:
host_tpl = urlutils.host_tuple(reply.url())
if set(errors).issubset(self._accepted_ssl_errors[host_tpl]):
reply.ignoreSslErrors()
elif set(errors).issubset(self._rejected_ssl_errors[host_tpl]):
pass
else:
err_string = '\n'.join('- ' + err.errorString() for err in
errors)
answer = self._ask('SSL errors - continue?\n{}'.format(
err_string), mode=usertypes.PromptMode.yesno,
owner=reply)
if answer:
reply.ignoreSslErrors()
self._accepted_ssl_errors[host_tpl] += errors
else:
self._rejected_ssl_errors[host_tpl] += errors
elif ssl_strict:
pass
else:

View File

@ -341,6 +341,14 @@ def filename_from_url(url):
return None
def host_tuple(url):
"""Get a (scheme, host, port) tuple.
This is suitable to identify a connection, e.g. for SSL errors.
"""
return (url.scheme(), url.host(), url.port())
class FuzzyUrlError(Exception):
"""Exception raised by fuzzy_url on problems."""