Expired SSL certificates don't raise an error

```
>>> requests.get('https://expired.badssl.com/', verify=True)
<Response [200]>
```

I'm expecting an SSL exception of some kind here, like it does for https://wrong.host.badssl.com/ 


Please have a read of our [contributing file](https://github.com/kennethreitz/requests/blob/master/CONTRIBUTING.md), which GitHub already asked you to do. Please then provide the information requested within: particularly, tell us **what version of Requests you're using** and **how you installed it**. Please also let me know what OS you're using, whether you have `pyopenssl`, `pyasn1`, `ndg-httpsclient`, or `certifi` installed, and what version of OpenSSL you are using.

The reason I ask all this is because I cannot reproduce this on my machine: my machine correctly fails to validate that certificate.


This is most recent requests, 2.8.1, with Python 2.7

It was installed as per the installation instructions here:

https://github.com/kennethreitz/requests#installation
OR
http://docs.python-requests.org/en/latest/user/install/#install

into a virtualenv, with nothing additional. I assumed from the installation instructions that nothing additional was necessary, and even looking through the docs (e.g. http://docs.python-requests.org/en/latest/user/advanced/#ssl-cert-verification ) I'm struggling to work out what else is necessary for correct SSL validation.  I installed certifi and that made no difference.

Looking further into urllib3 docs (https://urllib3.readthedocs.org/en/latest/security.html#openssl-pyopenssl ), if I do "pip install pyopenssl ndg-httpsclient pyasn1", then I get the expected failure.

I tried it on two machines - Linux Mint 17 and Ubuntu 12.04 - so I assumed this was not just a fluke with a bad setup, sorry for not providing enough information.


Aha, ok. So, `badssl.com` uses virtual hosting to provide multiple sub domains on one server. To do this in TLS requires an extension called SNI: Server Name Indication. Because the versions of Linux you are using are relatively old, they do not have the capability to do SNI using the standard library alone. Requests can use the three extra packages, if they're available, to do SNI: this is why adding them fixed the problem. 

Unfortunately, there's no way to tell the difference between a failure because of a lack of SNI and a failure because of a bad certificate. Confusingly, `badssl.com` serves a _valid_ wildcard certificate as its default, which means that the subdomains all mysteriously succeed.

Regardless, requests does the best it can out of the box. For a better experience, try Python 3.3+ or 2.7.9+, which can do SNI with the standard library alone. 


I really think this shouldn't be closed - surely a docs fix is needed? I followed the installation instructions, and yet had an installation that was subtly but importantly broken.


@spookylukey what do you want the installation instructions to say? "Make sure you use an operating system that ships versions of Python and OpenSSL that have these features or satisfy these minimum requirements"?


@sigmavirus24 - something like that, preferably with some information about the additional packages that are necessary, or under what (known) conditions you'll need to do more work. For a library that is explicitly "HTTP for humans", and has "Browser-style SSL Verification" high up on its list of features, this seems fairly important. The choice to rely on Python/OS for some of its functionality is a choice made by this library, and the user shouldn't be expected to know all the details.


the python module ssl has a flag, ssl.HAS_SNI, that can be used to warn
during installation/runtime.

On 2015-12-01 20:25, Ian Cordasco wrote:

> @spookylukey https://github.com/spookylukey what do you want the
> installation instructions to say? "Make sure you use an operating
> system that ships versions of Python and OpenSSL that have these
> features or satisfy these minimum requirements"?
> 
> —
> Reply to this email directly or view it on GitHub
> https://github.com/kennethreitz/requests/issues/2910#issuecomment-161085173.


Warning during installation is not possible: wheels don't run code at install time, and Python packaging strongly prefers them. 

We can warn at runtime, but I'm nervous about adding too many more warnings: users have complained bitterly about the ones we already have, that serve a security purpose. 

@spookylukey Note that the specific failure mode you encountered here was extremely uncommon, specifically because it was a _success_ mode. `badssl.com` served you a _valid_ certificate for the request you made! This is the rarest kind of website: one that uses SNI to deliberately _break_ your connection. Arguably, `badssl.com` needs a feature request to ensure that connections without SNI _fail_ outright!

Regardless, for the _common_ failure mode we have a [section of our FAQ](http://docs.python-requests.org/en/latest/community/faq/). When it comes to adding additional information to our install instructions, anything that requires manual user intervention is likely to be a non-starter. The most effective course would be a warning if SNI is not available on the platform, which I'm open to adding to urllib3.