Reputation: 141
I'm using Requests to connect to a RESTful API. The server I would like to reach use ssl with self-singed certificate.
cafile = "gateway.pem"
r = requests.get(request, auth=('admin', 'password'), verify=cafile)
the problem is I'm getting SSLError of hostname mismatch. there should be a way to disable the hostname checking without disabling certificate validation, as in many java implementations, but I can't find how to do it with requests in python.
stacktrace:
Traceback (most recent call last):
File "<pyshell#43>", line 1, in <module>
r = requests.get(request, auth=("admin", "password"), verify='gateway.pem')
File "C:\Python27\lib\site-packages\requests-2.0.0-py2.7.egg\requests\api.py", line 55, in get
return request('get', url, **kwargs)
File "C:\Python27\lib\site-packages\requests-2.0.0-py2.7.egg\requests\api.py", line 44, in request
return session.request(method=method, url=url, **kwargs)
File "C:\Python27\lib\site-packages\requests-2.0.0-py2.7.egg\requests\sessions.py", line 357, in request
resp = self.send(prep, **send_kwargs)
File "C:\Python27\lib\site-packages\requests-2.0.0-py2.7.egg\requests\sessions.py", line 460, in send
r = adapter.send(request, **kwargs)
File "C:\Python27\lib\site-packages\requests-2.0.0-py2.7.egg\requests\adapters.py", line 358, in send
raise SSLError(e)
SSLError: hostname '10.76.92.70' doesn't match u'lital.com'
How can this be done?
Upvotes: 14
Views: 39826
Reputation: 1362
It looks like this feature has been added to the latest version of requests. I've verified and it's working for me - just pass verify=False on the request - as shown in the example in the documentation:
requests.get('https://api.github.com', verify=False)
Upvotes: -4
Reputation: 653
I'm a little late to the party but requests_toolbelt
looks like it might help if you install version 0.7.0 or newer (my ubuntu 16.04 only has 0.6.0): https://toolbelt.readthedocs.io/en/latest/adapters.html#hostheaderssladapter
From the link:
Example usage:
>>> s.mount('https://', HostHeaderSSLAdapter())
>>> s.get("https://93.184.216.34", headers={"Host": "example.org"})
Upvotes: 8
Reputation: 1
If this is only for testing only then just add an entry in /etc/hosts to your local system (assuming you have access).
Upvotes: -5
Reputation: 2081
Did you look into the SSLContext.check_hostname
parameter?
You should be able to set it to False, and it should not check the hostname:
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = True
context.load_default_certs()
The only limitation is that this only works in Python 3.4 and later.
Reference: https://docs.python.org/3/library/ssl.html#ssl.SSLContext.check_hostname
Upvotes: 3
Reputation: 2713
Requests doesn't allow this directly, however you can provide a custom transport adapter which uses the features of the underlying urllib3
. The usage of transport adapters is covered in the requests documentation.
This code is not tested, but should work.
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.poolmanager import PoolManager
# Never check any hostnames
class HostNameIgnoringAdapter(HTTPAdapter):
def init_poolmanager(self, connections, maxsize, block=False):
self.poolmanager = PoolManager(num_pools=connections,
maxsize=maxsize,
block=block,
assert_hostname=False)
# Check a custom hostname
class CustomHostNameCheckingAdapter(HTTPAdapter):
def cert_verify(self, conn, url, verify, cert):
# implement me
host = custom_function_mapping_url_to_hostname(url)
conn.assert_hostname = host
return super(CustomHostNameCheckingAdapter,
self).cert_verify(conn, url, verify, cert)
In detail the assert_hostname
param works as follows:
If None
use the hostname from the URL, if False
suppress hostname checking, if a custom string validate against this string.
Upvotes: 10
Reputation: 6387
http://docs.python-requests.org/en/latest/user/advanced/#ssl-cert-verification
verify
keyword is a flag, not for providing certfile. You provided there non-empy string, which resolves to True
in boolean context.
Use cert=
keyword to provide path to certificate files, or disable verification with verify=False
.
EDIT: although documentation says you can actually pass CA path to verify=
, but there are no examples. It would be helpful to see whole traceback you are receiving.
Upvotes: -5