Spent a good part of a day on this, and I'm realllly at my wit's end. I have 1 machine "A" with Python 2.6.6/2.7.2 installed, and another machine "B" with Python 2.6.7/2.7.2 installed.
On machine A, I can get a SSLv3-encrypted website with urllib2.urlopen('https://fed.princeton.edu')
using Python 2.6.6 but not 2.7.2.
On machine B, I can't get that website using either Python version.
By can't get, I mean that I get the error:
Traceback:
File "/usr/local/lib/python2.7/dist-packages/Django-1.3.1-py2.7.egg/django/core/handlers/base.py" in get_response
111. response = callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python2.7/dist-packages/django_cas-2.0.3-py2.7.egg/django_cas/views.py" in login
78. user = auth.authenticate(ticket=ticket, service=service)
File "/usr/local/lib/python2.7/dist-packages/Django-1.3.1-py2.7.egg/django/contrib/auth/__init__.py" in authenticate
55. user = backend.authenticate(**credentials)
File "/usr/local/lib/python2.7/dist-packages/django_cas-2.0.3-py2.7.egg/django_cas/backends.py" in authenticate
72. username = _verify(ticket, service)
File "/usr/local/lib/python2.7/dist-packages/django_cas-2.0.3-py2.7.egg/django_cas/backends.py" in _verify_cas2
46. page = urlopen(url)
File "/usr/lib/python2.7/urllib.py" in urlopen
84. return opener.open(url)
File "/usr/lib/python2.7/urllib.py" in open
205. return getattr(self, name)(url)
File "/usr/lib/python2.7/urllib.py" in open_https
435. h.endheaders(data)
File "/usr/lib/python2.7/httplib.py" in endheaders
954. self._send_output(message_body)
File "/usr/lib/python2.7/httplib.py" in _send_output
814. self.send(msg)
File "/usr/lib/python2.7/httplib.py" in send
776. self.connect()
File "/usr/lib/python2.7/httplib.py" in connect
1161. self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file)
File "/usr/lib/python2.7/ssl.py" in wrap_socket
372. ciphers=ciphers)
File "/usr/lib/python2.7/ssl.py" in __init__
134. self.do_handshake()
File "/usr/lib/python2.7/ssl.py" in do_handshake
296. self._sslobj.do_handshake()
Exception Type: IOError at /login
Exception Value: [Errno socket error] [Errno 1] _ssl.c:503: error:140773F2:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert unexpected message
First, I'm confused that something that works on an earlier Python version doesn't work on the later on Machine A. I'm also very confused that something that works on 2.6.6 doesn't work on 2.6.7 (albeit on different machines). Why would this be?
Now I'm not sure the configuration for Python is the exact same on both, but import _ssl
and import httplib; httplib.HTTPSConnection
work for all versions on both machines. I've also tried curl -v https://fed.princeton.edu
and openssl fed.princeton.edu:https
on both machines, and these commands all work.
I've also done some research and found How to use urllib2 to get a webpage using SSLv3 encryption where the author seemed to have given up on urllib for libCurl (I'd rather not since I'm using django-cas, which uses urllib and I don't want to fiddle with that code too much).
Note: I just found http://bugs.python.org/issue11220, and the last post's solution allows me to use urlopen to open up the website. But how can I use their solution (which seems to be to use urllib2.install_opener(urllib2.build_opener(HTTPSHandlerV3()))
?) to resolve the my urlopen() in django-cas?
After a bit more experimenting I've just accepted that Python 2.6.6 is OK, but 2.6.7+ has this bug of not being able to fetch SSLv3-encrypted pages via urllib.urlopen()
.
I solved my problem by simply using the urllib2.install_opener
trick at http://bugs.python.org/issue11220, and modded django_cas so that this opener was installed before any urlopen()
call.