OpenSSL 1.0.1c and TLSv1 Handshake Failures #1083

Closed
jasonamyers opened this Issue Jan 3, 2013 · 6 comments

Comments

Projects
None yet
4 participants

I've been using requests in our application for a while; however, recently we've been working on interfacing with payment providers. We've been running into an issue where they use and older firewall/proxy combination that only allows TLSv1, in openssl versions prior to 1 this wasn't a big deal as it would initiate with a TLSv1 request. Beginning in OpenSSL version 1.0 this is no longer the case, and the negotiation process begins with SSL3, this causes these older devices and web servers (older apache) to just throw an EOF or fail the handshake. We need a way to specify an ssl version or negotiation starting point, so we can directly use requests with these older devices. This isn't probably much of a problem for many people; however, I did see a past issues #900, #851, #701, and #606. This isn't a problem on Mac OS X mountain lion unless you install openssl 1.0.1c (security needs), but it's now present by default on Windows and most Linux/Unix variants.

A more through explanation of my problem with code and detailed errors is available at:
http://stackoverflow.com/questions/14102416/python-requests-requests-exceptions-sslerror-errno-8-ssl-c504-eof-occurred

Contributor

piotr-dobrogost commented Jan 3, 2013

Requests uses shazow/urllib3# for handling this kind of things and you should start with finding out the way to do what you want in urllib3 and then return here and opt for exposing this functionality in Requests.

So urllib3 supports this already by enabled you to specify the SSL_Version when you wrap a socket for example in connectionpool.py:

def connect(self):
    # Add certificate verification
    sock = socket.create_connection((self.host, self.port), self.timeout)

    # Wrap socket using verification with the root certs in
    # trusted_root_certs
    self.sock = ssl_wrap_socket(sock, self.key_file, self.cert_file,
                                cert_reqs=self.cert_reqs,
                                ca_certs=self.ca_certs,
                                server_hostname=self.host,
                                ssl_version=self.ssl_version)

to:

def connect(self):
    # Add certificate verification
    sock = socket.create_connection((self.host, self.port), self.timeout)

    # Wrap socket using verification with the root certs in
    # trusted_root_certs
    self.sock = ssl_wrap_socket(sock, self.key_file, self.cert_file,
                                cert_reqs=self.cert_reqs,
                                ca_certs=self.ca_certs,
                                server_hostname=self.host,
                                ssl_version=ssl.PROTOCOL_TLSv1)

NOTE: this was supply by Favoretti on the Stack Overflow answer

Owner

Lukasa commented Jan 3, 2013

Requests' does not support doing this before version 1. Subsequent to version 1, you are expected to subclass the HTTPAdapter, like so:

from requests.adapters import HTTPAdapter
from requests.packages.urllib3.poolmanager import PoolManager
import ssl

class MyAdapter(HTTPAdapter):
    def init_poolmanager(self, connections, maxsize):
        self.poolmanager = PoolManager(num_pools=connections,
                                       maxsize=maxsize, 
                                       ssl_version=ssl.PROTOCOL_TLSv1)

When you've done that, you can do this:

import requests
s = requests.Session()
s.mount('https://', MyAdapter())

Any request through that session object will then use TLSv1.

Might have to write up some documentation for doing that. =)

EDIT: Authors note: I have not tried this code, I've only written it in here, so it might not be perfect.

You sir win an internet! Thank you so much!

Owner

Lukasa commented Jan 3, 2013

Glad I could help. =) Thanks for raising an issue!

Lukasa closed this Jan 3, 2013

akarca commented May 31, 2013

thanks Lukasa. I forked and patched: https://github.com/serdarakarca/requests

to use:
pip install --upgrade -e git+https://github.com/serdarakarca/requests#egg=requests

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment