I have an little app I wrote in Python and it used to work... until yesterday, when it suddenly started giving me an error in a HTTPS connection. I don't remember if there was an update, but both Python 2.7.3rc2 and Python 3.2 are failing just the same.
I googled it and found out that this happens when people are behind a proxy, but I'm not (and nothing have changed in my network since the last time it worked). My syster's computer running windows and Python 2.7.2 has no problems (in the same network).
>>> url = 'https://www.mediafire.com/api/user/get_session_token.php'
>>> response = urllib2.urlopen(url).read()
File "/usr/lib/python2.7/urllib2.py", line 126, in urlopen
return _opener.open(url, data, timeout)
File "/usr/lib/python2.7/urllib2.py", line 400, in open
response = self._open(req, data)
File "/usr/lib/python2.7/urllib2.py", line 418, in _open
'_open', req)
File "/usr/lib/python2.7/urllib2.py", line 378, in _call_chain
result = func(*args)
File "/usr/lib/python2.7/urllib2.py", line 1215, in https_open
return self.do_open(httplib.HTTPSConnection, req)
File "/usr/lib/python2.7/urllib2.py", line 1177, in do_open
raise URLError(err)
urllib2.URLError: <urlopen error [Errno 8] _ssl.c:504: EOF occurred in violation of protocol>
What's wrong? Any help is appreciated.
PS.: Older python versions don't work either, not in my system and not in a live session from USB, but DO work in a Ubuntu 11.10 live session.
This appears to be related to the addition of TLS 1.1 and 1.2 support to the version of OpenSSL found in 12.04. The connection failure can be reproduced with the OpenSSL command line tool:
The connection succeeds if I force the connection to use TLS 1.0 with the
-tls1
command line argument.I would suggest you file a bug report about this problem here:
https://bugs.launchpad.net/ubuntu/+filebug
For python novices like me, here is the way to override httplib the easiest way. At the top of your python script, include these lines:
From here on, you can use urllib or whatever you use just like you normally would.
Note: This is for python 2.7. For a python 3.x solution, you need to override the HTTPSConnection class found in http.client. I leave that as an exercise for the reader. :-)
You can avoid modifying the httplib.py file by modifying your HTTPSConnection object:
The request method creates a new socket only if connection.sock is not defined. Creating your own one adding the ssl_version parameter will make the request method use it. Then everything else works as usual.
I was having the same issue and this works for me.
Regards
The problem is in
ssl
, it has nothing to do with HTTP, so why patchinghttplib
if you can patchssl
. The following code should fix all SSL sockets including, but not limited to HTTPS, for Python 2.6+ (built inssl
, did not try withpyopenssl
).EDIT httplib.py (/usr/lib/pythonX.X/httplib.py on Linux)
FIND HTTPSConnection class declaration
Inside class code CHANGE line
TO
Then httplib HTTPS request should work
This issue is likely due to SSLv2 being disabled on the web server, but Python 2.x tries to establish a connection with PROTOCOL_SSLv23 by default.
Here's the link to my answer for a similar issue on Stack Overflow - https://stackoverflow.com/a/24166498/41957
Update: this is functionally the same as @temoto's answer above.
A simple fix that worked for me was to override SSL's default protocol: