Urllib.urlopen() works on SSLv3 urls with Python 2.6.6 on 1 machine, but not with 2.6.7/2.7.2 on another

10,618

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.

Share:
10,618
jwayne
Author by

jwayne

Updated on June 22, 2022

Comments

  • jwayne
    jwayne almost 2 years

    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?