parent
7b575460d5
commit
0124354b91
@ -41,6 +41,9 @@ Changed
|
|||||||
- `:completion-item-del` (`Ctrl-D`) can now be used in `:buffer` completion to
|
- `:completion-item-del` (`Ctrl-D`) can now be used in `:buffer` completion to
|
||||||
close a tab
|
close a tab
|
||||||
- Counts can now be used with special keybindings (e.g. with modifiers)
|
- Counts can now be used with special keybindings (e.g. with modifiers)
|
||||||
|
- Various SSL ciphers are now disabled by default. With recent Qt/OpenSSL
|
||||||
|
versions those already all are disabled, but with older versions they might
|
||||||
|
not be.
|
||||||
|
|
||||||
v0.6.2
|
v0.6.2
|
||||||
------
|
------
|
||||||
|
@ -26,7 +26,7 @@ import netrc
|
|||||||
from PyQt5.QtCore import (pyqtSlot, pyqtSignal, PYQT_VERSION, QCoreApplication,
|
from PyQt5.QtCore import (pyqtSlot, pyqtSignal, PYQT_VERSION, QCoreApplication,
|
||||||
QUrl, QByteArray)
|
QUrl, QByteArray)
|
||||||
from PyQt5.QtNetwork import (QNetworkAccessManager, QNetworkReply, QSslError,
|
from PyQt5.QtNetwork import (QNetworkAccessManager, QNetworkReply, QSslError,
|
||||||
QSslSocket)
|
QSslSocket, QSsl)
|
||||||
|
|
||||||
from qutebrowser.config import config
|
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,
|
||||||
@ -41,14 +41,73 @@ ProxyId = collections.namedtuple('ProxyId', 'type, hostname, port')
|
|||||||
_proxy_auth_cache = {}
|
_proxy_auth_cache = {}
|
||||||
|
|
||||||
|
|
||||||
|
def _is_secure_cipher(cipher):
|
||||||
|
"""Check if a given SSL cipher (hopefully) isn't broken yet."""
|
||||||
|
tokens = [e.upper() for e in cipher.name().split('-')]
|
||||||
|
if cipher.usedBits() < 128:
|
||||||
|
# https://codereview.qt-project.org/#/c/75943/
|
||||||
|
return False
|
||||||
|
# OpenSSL should already protect against this in a better way
|
||||||
|
# elif cipher.keyExchangeMethod() in ['DH', 'EDH']:
|
||||||
|
# # https://weakdh.org/
|
||||||
|
# return False
|
||||||
|
elif cipher.encryptionMethod().upper().startswith('RC4'):
|
||||||
|
# http://en.wikipedia.org/wiki/RC4#Security
|
||||||
|
# https://codereview.qt-project.org/#/c/148906/
|
||||||
|
return False
|
||||||
|
elif cipher.encryptionMethod().upper().startswith('DES'):
|
||||||
|
# http://en.wikipedia.org/wiki/Data_Encryption_Standard#Security_and_cryptanalysis
|
||||||
|
return False
|
||||||
|
elif 'MD5' in tokens:
|
||||||
|
# http://www.win.tue.nl/hashclash/rogue-ca/
|
||||||
|
return False
|
||||||
|
# OpenSSL should already protect against this in a better way
|
||||||
|
# elif (('CBC3' in tokens or 'CBC' in tokens) and (cipher.protocol() not in
|
||||||
|
# [QSsl.TlsV1_0, QSsl.TlsV1_1, QSsl.TlsV1_2])):
|
||||||
|
# # http://en.wikipedia.org/wiki/POODLE
|
||||||
|
# return False
|
||||||
|
### These things should never happen as those are already filtered out by
|
||||||
|
### either the SSL libraries or Qt - but let's be sure.
|
||||||
|
elif cipher.authenticationMethod() in ['aNULL', 'NULL']:
|
||||||
|
# Ciphers without authentication.
|
||||||
|
return False
|
||||||
|
elif cipher.encryptionMethod() in ['eNULL', 'NULL']:
|
||||||
|
# Ciphers without encryption.
|
||||||
|
return False
|
||||||
|
elif 'EXP' in tokens or 'EXPORT' in tokens:
|
||||||
|
# Weak export-grade ciphers
|
||||||
|
return False
|
||||||
|
elif 'ADH' in tokens:
|
||||||
|
# No MITM protection
|
||||||
|
return False
|
||||||
|
### This *should* happen ;)
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def init():
|
def init():
|
||||||
"""Disable insecure SSL ciphers on old Qt versions."""
|
"""Disable insecure SSL ciphers on old Qt versions."""
|
||||||
if not qtutils.version_check('5.3.0'):
|
if qtutils.version_check('5.3.0'):
|
||||||
# Disable weak SSL ciphers.
|
default_ciphers = QSslSocket.defaultCiphers()
|
||||||
# See https://codereview.qt-project.org/#/c/75943/
|
log.init.debug("Default Qt ciphers: {}".format(
|
||||||
good_ciphers = [c for c in QSslSocket.supportedCiphers()
|
', '.join(c.name() for c in default_ciphers)))
|
||||||
if c.usedBits() >= 128]
|
else:
|
||||||
QSslSocket.setDefaultCiphers(good_ciphers)
|
# https://codereview.qt-project.org/#/c/75943/
|
||||||
|
default_ciphers = QSslSocket.supportedCiphers()
|
||||||
|
log.init.debug("Supported Qt ciphers: {}".format(
|
||||||
|
', '.join(c.name() for c in default_ciphers)))
|
||||||
|
|
||||||
|
good_ciphers = []
|
||||||
|
bad_ciphers = []
|
||||||
|
for cipher in default_ciphers:
|
||||||
|
if _is_secure_cipher(cipher):
|
||||||
|
good_ciphers.append(cipher)
|
||||||
|
else:
|
||||||
|
bad_ciphers.append(cipher)
|
||||||
|
|
||||||
|
log.init.debug("Disabling bad ciphers: {}".format(
|
||||||
|
', '.join(c.name() for c in bad_ciphers)))
|
||||||
|
QSslSocket.setDefaultCiphers(good_ciphers)
|
||||||
|
|
||||||
|
|
||||||
class SslError(QSslError):
|
class SslError(QSslError):
|
||||||
|
Loading…
Reference in New Issue
Block a user