Use the TLSv1 SSL protocol version by default

This commit is contained in:
Kovid Goyal 2014-02-23 13:38:42 +05:30
parent 4e1cd543f5
commit 39ec9d5960

View File

@ -107,6 +107,10 @@ def match_hostname(cert, hostname):
class HTTPSConnection(httplib.HTTPSConnection): class HTTPSConnection(httplib.HTTPSConnection):
def __init__(self, ssl_version, *args, **kwargs):
httplib.HTTPSConnection.__init__(self, *args, **kwargs)
self.calibre_ssl_version = ssl_version
def connect(self): def connect(self):
"""Connect to a host on a given (SSL) port, properly verifying the SSL """Connect to a host on a given (SSL) port, properly verifying the SSL
certificate, both that it is valid and that its declared hostnames certificate, both that it is valid and that its declared hostnames
@ -117,21 +121,24 @@ class HTTPSConnection(httplib.HTTPSConnection):
if self._tunnel_host: if self._tunnel_host:
self.sock = sock self.sock = sock
self._tunnel() self._tunnel()
self.sock = ssl.wrap_socket(sock, cert_reqs=ssl.CERT_REQUIRED, ca_certs=self.cert_file) self.sock = ssl.wrap_socket(sock, cert_reqs=ssl.CERT_REQUIRED, ca_certs=self.cert_file, ssl_version=self.calibre_ssl_version)
getattr(ssl, 'match_hostname', match_hostname)(self.sock.getpeercert(), self.host) getattr(ssl, 'match_hostname', match_hostname)(self.sock.getpeercert(), self.host)
def get_https_resource_securely(url, cacerts='calibre-ebook-root-CA.crt', timeout=60, max_redirects=5): def get_https_resource_securely(
url, cacerts='calibre-ebook-root-CA.crt', timeout=60, max_redirects=5, ssl_version=None):
''' '''
Download the resource pointed to by url using https securely (verify server Download the resource pointed to by url using https securely (verify server
certificate). Ensures that redirects, if any, are also downloaded certificate). Ensures that redirects, if any, are also downloaded
securely. Needs a CA certificates bundle (in PEM format) to verify the securely. Needs a CA certificates bundle (in PEM format) to verify the
server's certificates. server's certificates.
''' '''
if ssl_version is None:
ssl_version = ssl.PROTOCOL_TLSv1
cacerts = P(cacerts, allow_user_override=False) cacerts = P(cacerts, allow_user_override=False)
p = urlsplit(url) p = urlsplit(url)
if p.scheme != 'https': if p.scheme != 'https':
raise ValueError('URL scheme must be https, not %s' % p.scheme) raise ValueError('URL scheme must be https, not %s' % p.scheme)
c = HTTPSConnection(p.hostname, p.port, cert_file=cacerts, timeout=timeout) c = HTTPSConnection(ssl_version, p.hostname, p.port, cert_file=cacerts, timeout=timeout)
with closing(c): with closing(c):
path = p.path or '/' path = p.path or '/'
if p.query: if p.query:
@ -144,7 +151,8 @@ def get_https_resource_securely(url, cacerts='calibre-ebook-root-CA.crt', timeou
newurl = response.getheader('Location', None) newurl = response.getheader('Location', None)
if newurl is None: if newurl is None:
raise ValueError('%s returned a redirect response with no Location header' % url) raise ValueError('%s returned a redirect response with no Location header' % url)
return get_https_resource_securely(newurl, cacerts=cacerts, timeout=timeout, max_redirects=max_redirects-1) return get_https_resource_securely(
newurl, cacerts=cacerts, timeout=timeout, max_redirects=max_redirects-1, ssl_version=ssl_version)
if response.status != httplib.OK: if response.status != httplib.OK:
raise ValueError('%s returned an unsupported http response code: %d (%s)' % ( raise ValueError('%s returned an unsupported http response code: %d (%s)' % (
url, response.status, httplib.responses.get(response.status, None))) url, response.status, httplib.responses.get(response.status, None)))