mirror of
https://github.com/Mikaela/Limnoria.git
synced 2025-01-25 19:44:13 +01:00
Verify server certificate, and deprecate Python < 2.7.9. Closes GH-1031.
This commit is contained in:
parent
c3dd5f8b64
commit
d922af1043
11
setup.py
11
setup.py
@ -236,10 +236,11 @@ setup(
|
|||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if sys.version_info < (2, 7, 0):
|
if sys.version_info < (2, 7, 9):
|
||||||
sys.stderr.write('+-----------------------------------------------+\n')
|
sys.stderr.write('+------------------------------------------------+\n')
|
||||||
sys.stderr.write('| Running Limnoria on Python 2.6 is deprecated. |\n')
|
sys.stderr.write('| Running Limnoria on Python versions older than |\n')
|
||||||
sys.stderr.write('| Please consider upgrading to Python 3.x. |\n')
|
sys.stderr.write('| 2.7.9 is deprecated. |\n')
|
||||||
sys.stderr.write('+-----------------------------------------------+\n')
|
sys.stderr.write('| Please consider upgrading to Python 3.x. |\n')
|
||||||
|
sys.stderr.write('+------------------------------------------------+\n')
|
||||||
|
|
||||||
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
||||||
|
17
src/conf.py
17
src/conf.py
@ -1163,6 +1163,23 @@ registerGlobalValue(supybot.protocols.http, 'proxy',
|
|||||||
through. The value should be of the form 'host:port'.""")))
|
through. The value should be of the form 'host:port'.""")))
|
||||||
utils.web.proxy = supybot.protocols.http.proxy
|
utils.web.proxy = supybot.protocols.http.proxy
|
||||||
|
|
||||||
|
###
|
||||||
|
# supybot.protocols.ssl
|
||||||
|
###
|
||||||
|
registerGroup(supybot.protocols, 'ssl')
|
||||||
|
class SSLVerifyMode(registry.OnlySomeStrings):
|
||||||
|
validStrings = ('required', 'optional', 'none')
|
||||||
|
def __call__(self):
|
||||||
|
import ssl
|
||||||
|
value = super(SSLVerifyMode, self).__call__()
|
||||||
|
return getattr(ssl, 'CERT_' + value.upper())
|
||||||
|
registerGlobalValue(supybot.protocols.ssl, 'verifyMode',
|
||||||
|
SSLVerifyMode('required', _("""Determines whether server certificates '
|
||||||
|
'will be verified. Valid values are "required", "optional", and "none". '
|
||||||
|
'The default and recommended setting is "required", which checks the '
|
||||||
|
'server certificate is signed by a known Certificate Authority, and '
|
||||||
|
'aborts the connection if it is not.""")))
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
# HTTP server
|
# HTTP server
|
||||||
|
@ -238,9 +238,9 @@ class SocketDriver(drivers.IrcDriver, drivers.ServersMixin):
|
|||||||
if wait:
|
if wait:
|
||||||
self.scheduleReconnect()
|
self.scheduleReconnect()
|
||||||
return
|
return
|
||||||
server = self._getNextServer()
|
self.server = self._getNextServer()
|
||||||
socks_proxy = getattr(conf.supybot.networks, self.irc.network) \
|
network_config = getattr(conf.supybot.networks, self.irc.network)
|
||||||
.socksproxy()
|
socks_proxy = network_config.socksproxy()
|
||||||
try:
|
try:
|
||||||
if socks_proxy:
|
if socks_proxy:
|
||||||
import socks
|
import socks
|
||||||
@ -249,16 +249,16 @@ class SocketDriver(drivers.IrcDriver, drivers.ServersMixin):
|
|||||||
'using direct connection instead.')
|
'using direct connection instead.')
|
||||||
socks_proxy = ''
|
socks_proxy = ''
|
||||||
if socks_proxy:
|
if socks_proxy:
|
||||||
address = server[0]
|
address = self.server[0]
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
address = utils.net.getAddressFromHostname(server[0],
|
address = utils.net.getAddressFromHostname(self.server[0],
|
||||||
attempt=self._attempt)
|
attempt=self._attempt)
|
||||||
except (socket.gaierror, socket.error) as e:
|
except (socket.gaierror, socket.error) as e:
|
||||||
drivers.log.connectError(self.currentServer, e)
|
drivers.log.connectError(self.currentServer, e)
|
||||||
self.scheduleReconnect()
|
self.scheduleReconnect()
|
||||||
return
|
return
|
||||||
port = server[1]
|
port = self.server[1]
|
||||||
drivers.log.connect(self.currentServer)
|
drivers.log.connect(self.currentServer)
|
||||||
try:
|
try:
|
||||||
self.conn = utils.net.getSocket(address, port=port,
|
self.conn = utils.net.getSocket(address, port=port,
|
||||||
@ -276,9 +276,17 @@ class SocketDriver(drivers.IrcDriver, drivers.ServersMixin):
|
|||||||
try:
|
try:
|
||||||
# Connect before SSL, otherwise SSL is disabled if we use SOCKS.
|
# Connect before SSL, otherwise SSL is disabled if we use SOCKS.
|
||||||
# See http://stackoverflow.com/q/16136916/539465
|
# See http://stackoverflow.com/q/16136916/539465
|
||||||
self.conn.connect((address, server[1]))
|
self.conn.connect((address, port))
|
||||||
if getattr(conf.supybot.networks, self.irc.network).ssl():
|
if network_config.ssl():
|
||||||
self.starttls()
|
self.starttls()
|
||||||
|
elif not network_config.requireStarttls():
|
||||||
|
drivers.log.critical(('Connection to network %s'
|
||||||
|
'does not use SSL/TLS, which makes it vulnerable to '
|
||||||
|
'man-in-the-middle attacks and passive eavesdropping. '
|
||||||
|
'You should consider upgrading your connection to SSL/TLS '
|
||||||
|
'<http://doc.supybot.aperio.fr/en/latest/use/faq.html#how-to-make-a-connection-secure>')
|
||||||
|
% self.irc.network)
|
||||||
|
|
||||||
def setTimeout():
|
def setTimeout():
|
||||||
self.conn.settimeout(conf.supybot.drivers.poll())
|
self.conn.settimeout(conf.supybot.drivers.poll())
|
||||||
conf.supybot.drivers.poll.addCallback(setTimeout)
|
conf.supybot.drivers.poll.addCallback(setTimeout)
|
||||||
@ -353,7 +361,29 @@ class SocketDriver(drivers.IrcDriver, drivers.ServersMixin):
|
|||||||
drivers.log.warning('Could not find cert file %s.' %
|
drivers.log.warning('Could not find cert file %s.' %
|
||||||
certfile)
|
certfile)
|
||||||
certfile = None
|
certfile = None
|
||||||
self.conn = ssl.wrap_socket(self.conn, certfile=certfile)
|
try:
|
||||||
|
self.conn = utils.net.ssl_wrap_socket(self.conn,
|
||||||
|
logger=drivers.log, hostname=self.server[0],
|
||||||
|
certfile=certfile,
|
||||||
|
verify_mode=conf.supybot.protocols.ssl.verifyMode())
|
||||||
|
except ssl.CertificateError as e:
|
||||||
|
drivers.log.critical(('Certificate validation failed when '
|
||||||
|
'connecting to %s: %s\n'
|
||||||
|
'This means someone is doing a man-in-the-middle attack '
|
||||||
|
'on your connection.')
|
||||||
|
% (self.irc.network, e.args[0]))
|
||||||
|
raise ssl.SSLError('Aborting because of failed certificate '
|
||||||
|
'verification.')
|
||||||
|
except ssl.SSLError as e:
|
||||||
|
drivers.log.critical(('Certificate validation failed when '
|
||||||
|
'connecting to %s: %s\n'
|
||||||
|
'This means someone is doing a man-in-the-middle attack '
|
||||||
|
'on your connection, or because the server\'s '
|
||||||
|
'certificate is not trusted.')
|
||||||
|
% (self.irc.network, e.args[1]))
|
||||||
|
raise ssl.SSLError('Aborting because of failed certificate '
|
||||||
|
'verification.')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Driver = SocketDriver
|
Driver = SocketDriver
|
||||||
|
@ -33,6 +33,7 @@ Simple utility modules.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
import ssl
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
from .web import _ipAddr, _domain
|
from .web import _ipAddr, _domain
|
||||||
@ -128,4 +129,26 @@ def isIPV6(s):
|
|||||||
return bruteIsIPV6(s)
|
return bruteIsIPV6(s)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
if hasattr(ssl, 'create_default_context'):
|
||||||
|
def ssl_wrap_socket(conn, hostname, logger, certfile=None,
|
||||||
|
verify_mode=ssl.CERT_REQUIRED, **kwargs):
|
||||||
|
context = ssl.create_default_context(**kwargs)
|
||||||
|
context.verify_mode = verify_mode
|
||||||
|
if certfile:
|
||||||
|
context.load_cert_chain(certfile)
|
||||||
|
return context.wrap_socket(conn, server_hostname=hostname)
|
||||||
|
else:
|
||||||
|
def ssl_wrap_socket(conn, hostname, logger, certfile=None, ca_certs=None,
|
||||||
|
verify_mode=ssl.CERT_REQUIRED):
|
||||||
|
logger.critical('This Python version does not support SSL contexts, '
|
||||||
|
'which makes your connection vulnerable to man-in-the-middle '
|
||||||
|
'attacks. You should consider upgrading to Python 3 '
|
||||||
|
'(or at least 2.7.9).')
|
||||||
|
# TLSv1.0 is the only TLS version Python < 2.7.9 supports
|
||||||
|
# (besides SSLv2 and v3, which are known to be insecure)
|
||||||
|
return ssl.wrap_socket(conn, certfile=certfile, ca_certs=ca_certs,
|
||||||
|
ssl_version=ssl.ssl.PROTOCOL_TLSv1, verify_mode=verify_mode)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
||||||
|
Loading…
Reference in New Issue
Block a user