Skip to content

Commit 5bff06d

Browse files
committed
Make certificate validation optional with an HTTPRequest parameter
for consistency between curl and simple HTTPClients.
1 parent cfa8857 commit 5bff06d

File tree

3 files changed

+22
-9
lines changed

3 files changed

+22
-9
lines changed

tornado/httpclient.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,8 @@ def __init__(self, url, method="GET", headers=None, body=None,
378378
network_interface=None, streaming_callback=None,
379379
header_callback=None, prepare_curl_callback=None,
380380
proxy_host=None, proxy_port=None, proxy_username=None,
381-
proxy_password='', allow_nonstandard_methods=False):
381+
proxy_password='', allow_nonstandard_methods=False,
382+
validate_cert=True, ca_certs=None):
382383
if headers is None:
383384
headers = httputil.HTTPHeaders()
384385
if if_modified_since:
@@ -420,6 +421,12 @@ def __init__(self, url, method="GET", headers=None, body=None,
420421
self.header_callback = header_callback
421422
self.prepare_curl_callback = prepare_curl_callback
422423
self.allow_nonstandard_methods = allow_nonstandard_methods
424+
# SSL certificate validation:
425+
# validate_cert: boolean, set to False to disable validation
426+
# ca_certs: filename of CA certificates in PEM format, or
427+
# None to use defaults
428+
self.validate_cert = validate_cert
429+
self.ca_certs = ca_certs
423430
self.start_time = time.time()
424431

425432

@@ -556,6 +563,11 @@ def _curl_setup_request(curl, request, buffer, headers):
556563
curl.setopt(pycurl.PROXYUSERPWD, credentials)
557564
else:
558565
curl.setopt(pycurl.PROXY, '')
566+
curl.setopt(pycurl.SSL_VERIFYPEER, request.validate_cert)
567+
if request.ca_certs is not None:
568+
curl.setopt(pycurl.CAINFO, request.ca_certs)
569+
else:
570+
curl.unsetopt(pycurl.CAINFO)
559571

560572
# Set the request method through curl's retarded interface which makes
561573
# up names for almost every single method

tornado/simple_httpclient.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,14 @@ def __init__(self, io_loop, client, request, callback):
143143
host = self.client.hostname_mapping.get(host, host)
144144

145145
if parsed.scheme == "https":
146-
ssl_options = dict(
147-
cert_reqs=ssl.CERT_REQUIRED,
148-
ca_certs=os.path.dirname(__file__) + '/ca-certificates.crt',
149-
)
146+
ssl_options = {}
147+
if request.validate_cert:
148+
ssl_options["cert_reqs"] = ssl.CERT_REQUIRED
149+
if request.ca_certs is not None:
150+
ssl_options["ca_certs"] = request.ca_certs
151+
else:
152+
ssl_options["ca_certs"] = (os.path.dirname(__file__) +
153+
'/ca-certificates.crt')
150154
self.stream = SSLIOStream(socket.socket(),
151155
io_loop=self.io_loop,
152156
ssl_options=ssl_options)

tornado/test/httpserver_test.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,9 @@ def get_httpserver_options(self):
3737
keyfile=os.path.join(test_dir, 'test.key')))
3838

3939
def fetch(self, path, **kwargs):
40-
def disable_cert_check(curl):
41-
# Our certificate was not signed by a CA, so don't check it
42-
curl.setopt(pycurl.SSL_VERIFYPEER, 0)
4340
self.http_client.fetch(self.get_url(path).replace('http', 'https'),
4441
self.stop,
45-
prepare_curl_callback=disable_cert_check,
42+
validate_cert=False,
4643
**kwargs)
4744
return self.wait()
4845

0 commit comments

Comments
 (0)