2012-03-23 11 views
10

trascorso una buona parte di una giornata su questo, e io sono al mio realllly con la fine Ho 1 macchina "A" con Python 2.6.6/2.7.2 installato, e un'altra macchina "B" con Python 2.6.7/2.7.2 installato.urllib.urlopen() funziona su SSLv3 gli URL con Python 2.6.6 su 1 macchina, ma non con la 2.6.7/2.7.2 su un altro

Su macchina A, posso ottenere un sito web SSLv3 crittografato con urllib2.urlopen('https://fed.princeton.edu') utilizzando Python 2.6.6, ma non 2.7.2.

Sulla macchina B, non riesco a ottenere quel sito Web utilizzando la versione di Python.

da non può ottenere, voglio dire che ho l'errore:

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 

In primo luogo, sono confuso che qualcosa che funziona su una versione precedente di Python non funziona sul tardi sulla macchina A Sono anche molto confuso dal fatto che qualcosa che funziona su 2.6.6 non funzioni su 2.6.7 (anche se su macchine diverse). Perché dovrebbe essere?

Ora non sono sicuro che la configurazione di Python sia la stessa esatta su entrambi, ma import _ssl e import httplib; httplib.HTTPSConnection funzionano per tutte le versioni su entrambe le macchine. Ho anche provato curl -v https://fed.princeton.edu e openssl fed.princeton.edu:https su entrambe le macchine, e questi comandi tutto il lavoro.

Ho fatto anche qualche ricerca e ho trovato How to use urllib2 to get a webpage using SSLv3 encryption dove l'autore sembrava aver rinunciato a urllib per libcurl (Preferirei di no dal momento che sto usando django-cas, che utilizza urllib e io non voglio a giocherellare troppo con quel codice).


Nota: Ho appena trovato http://bugs.python.org/issue11220, e la soluzione dell'ultimo messaggio mi permette di usare urlopen per aprire il sito. Ma come posso usare la loro soluzione (che sembra essere quello di utilizzare urllib2.install_opener(urllib2.build_opener(HTTPSHandlerV3()))?) Per risolvere il mio urlopen() in django-cas?

+0

Esistono diverse versioni di OpenSSL sui due sistemi? – larsks

risposta

6

Dopo un po 'più di sperimentazione ho appena accettato che Python 2.6.6 sia OK, ma 2.6.7+ ha questo bug di non essere in grado di recuperare pagine crittografate con SSLv3 tramite urllib.urlopen().

ho risolto il problema, semplicemente utilizzando il urllib2.install_opener trick a http://bugs.python.org/issue11220, e django_cas modded in modo che questa apertura è stato installato prima di qualsiasi urlopen() chiamata.

0

Puoi scimmia-patch ssl.wrap_socket() sovrascrivendo il parametro SSL_VERSION parola chiave. Il seguente codice può essere usato così com'è. Metti questo prima di urlopen().

import ssl 
from functools import wraps 
def sslwrap(func): 
    @wraps(func) 
    def bar(*args, **kw): 
     kw['ssl_version'] = ssl.PROTOCOL_TLSv1 
     return func(*args, **kw) 
    return bar 

ssl.wrap_socket = sslwrap(ssl.wrap_socket) 

EDIT: Ho aggiornato il codice precedente dopo aver realizzato che functools.partial realtà non restituire una funzione, e non sarebbe adatta in questo caso. Chunk come potrebbe sembrare, il codice sopra è ancora la soluzione migliore che conosco finora.

+3

Questo non funziona per me. – gozzilli