Seeing SSLError: [Errno 185090050] _ssl.c:340: error:0B084002:x509 certificate routines:X509_load_cert_crl_file:system lib

In our logs, I noticed this error when using requests to perform a POST to Facebook's Graph API using HTTPS:

```
File "/home/api/api/lib/python2.7/site-packages/requests/api.py", line 85, in post
    return request('post', url, data=data, **kwargs)
  File "/home/api/api/lib/python2.7/site-packages/requests/api.py", line 40, in request
    return s.request(method=method, url=url, **kwargs)
  File "/home/api/api/lib/python2.7/site-packages/requests/sessions.py", line 208, in request
    r.send(prefetch=prefetch)
  File "/home/api/api/lib/python2.7/site-packages/requests/models.py", line 584, in send
    raise SSLError(e)
SSLError: [Errno 185090050] _ssl.c:340: error:0B084002:x509 certificate routines:X509_load_cert_crl_file:system lib
```

This is the first time I've seen it... could it be at all related to the cacerts file included in one of the dependencies of requests?

Is it related to this at all? https://github.com/kennethreitz/requests/issues/30


Do you have `certifi` installed?


Yessir. I just double checked on all our servers and ran `pip freeze` in each of our virtualenvs:

... snip ...
certifi==0.0.8
chardet==1.0.1
httplib2==0.7.2
requests==0.11.1
... snip ...


Hmm, can you do this?

``` python
import cerifi
print certifi.where()
```

And then make sure that file is readable?


I checked on all our servers:

> > > import certifi
> > > print certifi.where()
> > > ..snip../lib/python2.7/site-packages/certifi/cacert.pem

$ ll ../lib/python2.7/site-packages/certifi/cacert.pem
-rw-rw-r-- 1 ..snip.. Apr 19 18:29 ..snip../lib/python2.7/site-packages/certifi/cacert.pem


There shouldn't be a problem then :)


Is this when making _any_ HTTPS request?


Sorry, I thought I mentioned earlier, this is the first time I've ever seen the issue in the logs, and we're doing an awful lot of https requests, so maybe it's just an anomaly, some malformed packet or something...maybe a neutrino ;-)


Letcha know if I see this more...


I am seeing this same error

SSLError: [Errno 185090050] _ssl.c:340: error:0B084002:x509 certificate routines:X509_load_cert_crl_file:system lib


Clarification, For me error is only happening when program is packaged by pyinstaller


I'm having the same problem. I'm using ActivePython and Windows 7 64 bit:

requests.exceptions.SSLError: [Errno 185090050] _ssl.c:340: error:0B084002:x509
certificate routines:X509_load_cert_crl_file:system lib

Program:

import requests
r = requests.get('https://github.com/timeline.json')
print r

i have all the packages mentioned in this thread and certifi.where() prints out 
C:\Python27\lib\site-packages\certifi\cacert.pem
File exists and is readable. 

Any ideas ?


@gkappel:  
I also faced a similar error when using pyinstaller with Httplib2.
You need to explicitly pass the path to ssl client cert file to the 'cert' argument http request. Also, you would need to package your. .pem file as a data file in pyinstaller.

Hope it helps!


@sahilgupta 

That works! Thanks a lot.


@sahilgupta Could you elaborate on how you fixed this? I'm having this problem as well and it would be great to know your solution.


I did something like this:

``` python
import certifi
print certifi.where()
..snip../lib/python2.7/site-packages/certifi/cacert.pem
```

to get a cert file and then copied it to somewhere in my python project directory.

``` python
h = httplib2.Http(ca_certs= '/this/new/path/to/cacert.pem')
```

To package this .pem file as a data file with pyinstaller, follow:
http://stackoverflow.com/questions/7674790/bundling-data-files-with-pyinstaller-onefile

I don't have the exact code lying around at the moment, so you might have to play a bit to get it working.  I guess ideally we shouldn't need to do all this because httplib2 comes with a cert file of its own, but pyinstaller probably fails to pack this alongwith and hence the call fails from a binary compiled with pyinstaller.

Anyways, hope this helps!


@sahilgupta Thanks for the help! I think I've figured out how to package the data file with PyInstaller, but I couldn't figure out how to pass that to requests to use, and I've already got enough code that uses requests that I'm not willing to switch to httplib2. For now, I've just disabled SSL verification.


@seanfisk  Did some further digging. Specifying certificate is even easier in requests than with httplib2. Try something on the lines of :

``` python
os.environ['REQUESTS_CA_BUNDLE'] = '/path/to/cacert.pem'
```

and enable SSL verification.
This would force requests to use this certificate instead of the default one as per http://kennethreitz.com/major-progress-for-requests.html


@sahilgupta Thanks, that worked. It was actually a RTFM on my part. Checked the [SSL Verification section](http://docs.python-requests.org/en/latest/user/advanced/#ssl-cert-verification) in the requests documentation and it was right there, and now it works. I could swear I was passing the path to `verify` before, but it's working now, so who cares. Here's the code I used for future reference:

``` python
#!/usr/bin/env python
# requests_ssl.py
# main script

import requests
import os
import sys

# stolen and adpated from <http://stackoverflow.com/questions/7674790/bundling-data-files-with-pyinstaller-onefile>
def resource_path(relative):
    return os.path.join(getattr(sys, '_MEIPASS', os.path.abspath(".")),
                        relative)

cert_path = resource_path('cacert.pem')
# this would also work, but I'd rather not set unnecessary env vars
# os.environ['REQUESTS_CA_BUNDLE'] = cert_path
print requests.get('https://www.google.com/', verify=cert_path).text
```

``` python
# PyInstaller spec file
a = Analysis(
    ['requests_ssl.py'],
    pathex=['.'],
    hiddenimports=[],
    hookspath=None)
a.datas.append(('cacert.pem', 'cacert.pem', 'DATA'))
pyz = PYZ(a.pure)
exe = EXE(
    pyz,
    a.scripts,
    a.binaries,
    a.zipfiles,
    a.datas,
    name=os.path.join('dist', 'requests_ssl'),
    debug=False,
    strip=None,
    upx=True,
    console=True)
```

Thanks for your help!


Cool! Glad that you got it working :)


I had the same error on fedora based system and `pip install certifi` solved the issue.
I had installed requests via pip before, but on that particular machine certifi was not installed automatically when pip install requests.

Versions:

```
requests==0.14.2
certifi==0.0.8
```

Note, that on debian squeeze or mac I didn't have this issue and I didn't need to install certifi by hand.


Which version of requests do you have installed and how did you install it? 

@viciu thanks for editing your comment with the versions.


This is unfortunate; Requests is now supposed to use the system certificate bundle `/etc/pki/tls/certs/ca-bundle.crt` on Fedora by default, without requiring certifi.


@slingamn is it possible @viciu doesn't have that path? Maybe some other package he's installed removed it/replaced it/moved it?


Yeah, that's possible. This can be tested by inspecting the following values:

``` python
import requests.utils
# this is the theoretical OS-packaged CA bundle, if available
print requests.utils.get_os_ca_bundle_path()
# this is the path that is used in practice
print requests.utils.DEFAULT_CA_BUNDLE_PATH
```


Actually, heh. Ever since c3ad7af06c5fdd603d4ac114cfa114a12a386d10, the OS bundle path is a no-op since a CA bundle (`requests/cacert.pem`) is versioned together with Requests.


@slingamn: Given #1065 (which was opened after a discussion on #1033), can we close this?


@Lukasa I'm for closing it. 


Let's do it. We can always reopen it.


I see a similar problem while running bandersnatcher on Ubuntu 10.04 LTS
bandersnatch==1.0dev
cov-core==1.7
coverage==3.6
distribute==0.6.35
mercurial==2.5.2
mock==1.0.1
py==1.4.13
pytest==2.3.4
pytest-cov==1.6
requests==1.1.0
virtualenv==1.6.1
wsgiref==0.1.2

2013-03-26 17:25:49,493 ERROR: Error syncing package: OpenCorePaste
Traceback (most recent call last):
  File "/srv/pypi/lib/python2.7/site-packages/bandersnatch-1.0dev-py2.7.egg/bandersnatch/package.py", line 56, in sync
    self.sync_release_files()
  File "/srv/pypi/lib/python2.7/site-packages/bandersnatch-1.0dev-py2.7.egg/bandersnatch/package.py", line 74, in sync_release_files
    self.download_file(release_file['url'], release_file['md5_digest'])
  File "/srv/pypi/lib/python2.7/site-packages/bandersnatch-1.0dev-py2.7.egg/bandersnatch/package.py", line 137, in download_file
    r = requests.get(url, stream=True)
  File "/srv/pypi/lib/python2.7/site-packages/requests-1.1.0-py2.7.egg/requests/api.py", line 55, in get
    return request('get', url, *_kwargs)
  File "/srv/pypi/lib/python2.7/site-packages/requests-1.1.0-py2.7.egg/requests/api.py", line 44, in request
    return session.request(method=method, url=url, *_kwargs)
  File "/srv/pypi/lib/python2.7/site-packages/requests-1.1.0-py2.7.egg/requests/sessions.py", line 279, in request
    resp = self.send(prep, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies)
  File "/srv/pypi/lib/python2.7/site-packages/requests-1.1.0-py2.7.egg/requests/sessions.py", line 374, in send
    r = adapter.send(request, **kwargs)
  File "/srv/pypi/lib/python2.7/site-packages/requests-1.1.0-py2.7.egg/requests/adapters.py", line 213, in send
    raise SSLError(e)
SSLError: [Errno 185090050] _ssl.c:340: error:0B084002:x509 certificate routines:X509_load_cert_crl_file:system lib

The error happens with https downloads from PyPI.


I'm experiencing this when import from a zip file. Copy the `cacert.pem` to approot will solve it:

```
os.environ['REQUESTS_CA_BUNDLE'] = os.path.join(app_root, 'cacert.pem')
```

I have not set up a clean env to reproduce it, but I have tested it in my app and narrow down it to be zip related.

FYI, the zip file way is how my cloud-host suggested to upload virtualenv packages. It's like:

```
# bundle_it.sh
cp ./virtualenv.bundle/requests/cacert.pem ./cacert.pem
cd virtualenv.bundle/
zip -r ../virtualenv.bundle.zip .
# index.wsgi
sys.path.insert(0, os.path.join(app_root, 'virtualenv.bundle.zip'))
```