--- contrib/python/tornado/tornado-4/tornado/curl_httpclient.py (index) +++ contrib/python/tornado/tornado-4/tornado/curl_httpclient.py (working tree) @@ -364,7 +364,17 @@ class CurlAsyncHTTPClient(AsyncHTTPClient): curl.setopt(pycurl.SSL_VERIFYPEER, 0) curl.setopt(pycurl.SSL_VERIFYHOST, 0) if request.ca_certs is not None: - curl.setopt(pycurl.CAINFO, request.ca_certs) + cafile, capath, cadata = None, None, None + if callable(request.ca_certs): + cafile, capath, cadata = request.ca_certs() + else: + cafile = request.ca_certs + if cafile is not None: + curl.setopt(pycurl.CAINFO, cafile) + if capath is not None: + curl.setopt(pycurl.CAPATH, capath) + if cadata is not None: + curl.set_ca_certs(cadata) else: # There is no way to restore pycurl.CAINFO to its default value # (Using unsetopt makes it reject all certificates). --- contrib/python/tornado/tornado-4/tornado/netutil.py (index) +++ contrib/python/tornado/tornado-4/tornado/netutil.py (working tree) @@ -64,6 +64,8 @@ if hasattr(ssl, 'SSLContext'): # of a context is to authentiate the opposite side of the connection. _client_ssl_defaults = ssl.create_default_context( ssl.Purpose.SERVER_AUTH) + # load ca certs bundled with binary + _client_ssl_defaults.load_verify_locations(certifi.where()) _server_ssl_defaults = ssl.create_default_context( ssl.Purpose.CLIENT_AUTH) else: