2013-09-07 20 views
5

Uwaga: ten kod działa poprawnie w systemie Ubuntu, ale nie na Macu, a zamiast zmieniać ustawienia Mac/Pythona lokalnie Próbuję wprowadzić zmiany w kodzie, aby działał wszędzie ..Python httplib SSL23_GET_SERVER_HELLO: nieznany protokół

import ssl 
import httplib 
httplib.HTTPConnection(server, port, timeout) 

ale wyrzuca błąd:

[Errno 1] _ssl.c:503: error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol

teraz kod nie używa urllib.request zamiast korzystania httplib

Chcę zmienić kod tak zajmie to SSLv3 jako domyślnego protokołu, coś takiego:

ssl.SSLContext(ssl.PROTOCOL_SSLv3) 

Rozejrzałem się i znalazłem kilka linków, ale nic nie działa!

this link is for ubuntu

link for python urllib and cURL

python bug fix, but again for urllib

Odpowiedz

7

Uwaga: Konstruktor HTTPSConnection pozwala przekazać ssl context jako argument od pytona 2.7.9, które powinny być stosowane w takim przypadku.

Ta odpowiedź poprzedza tę zmianę, a zatem dotyczy tylko nieaktualnych wersji Pythona.


httplib.HTTPSConnection.connect po prostu wywołuje ssl.wrap_socket na otwarciu gniazda do initalize połączenia https, niestety nie można określić żadnych parametrów w python2.7 (python3 pozwala passing the SSLContext).

Jeśli chcesz określić wersję protokołu, trzeba by małpa plaster jeden z tych dwóch:

Metoda 1 patch httplib.HTTPSConnection.connect:

import httplib 
import socket 
import ssl 

def connect_patched(self): 
    "Connect to a host on a given (SSL) port." 

    sock = socket.create_connection((self.host, self.port), 
            self.timeout, self.source_address) 
    if self._tunnel_host: 
     self.sock = sock 
     self._tunnel() 
    self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, 
           ssl_version=ssl.PROTOCOL_SSLv3) 

httplib.HTTPSConnection.connect = connect_patched 

Zmienia wersję protokołu do wszystkie połączenia wykonane z HTTPSConnection.

Metoda 2 patch ssl.wrap_socket:

import ssl 

wrap_socket_orig = ssl.wrap_socket 

def wrap_socket_patched(sock, keyfile=None, certfile=None, 
         server_side=False, cert_reqs=ssl.CERT_NONE, 
         ssl_version=ssl.PROTOCOL_SSLv3, ca_certs=None, 
         do_handshake_on_connect=True, 
         suppress_ragged_eofs=True, ciphers=None): 
    return wrap_socket_orig(sock, keyfile, certfile, server_side, 
          cert_reqs, ssl_version, ca_certs, 
          do_handshake_on_connect, 
          suppress_ragged_eofs, ciphers) 

ssl.wrap_socket = wrap_socket_patched 

To zmienia domyślną wersję protokołu dla cały kod, który wykorzystuje wrap_socket wpływa zatem także innych bibliotek.

edit:

Metoda 3: ponieważ httplib rzeczywiście ma dostęp tylko wrap_socket z ssl, można też po prostu zastąpić httplib.ssl z klasą zapewniając wrap_socket.Korzystanie functools.partial sprawia, że ​​bardzo elegancki napisać to:

import httplib 
import ssl 
from functools import partial 

class fake_ssl: 
    wrap_socket = partial(ssl.wrap_socket, ssl_version=ssl.PROTOCOL_SSLv3) 

httplib.ssl = fake_ssl 
+1

Próbowałem metody 3, a teraz jego rzucanie „Procedury SSL: SSL3_GET_RECORD: błędny numer wersji”, ale jeśli mogę sprawdzić protokół serwera, „OpenSSL s_client -connect host: port | grep Protokół "zwraca" Protokół: SSLv3 "! Spróbuję innych metod i lyk .. – Peter

+1

wypróbowałem wszystkie 3 metody teraz otrzymuję błąd (dla wszystkich metod) "Procedury SSL: SSL3_GET_RECORD: zły numer wersji" – Peter

+0

Wynik powinien być taki sam, bez względu na metodę powyższych metod posługiwać się. Czy wypróbowałeś inny versoins protokołu? Nie jestem pewien, jak odtworzyć błąd, który otrzymujesz. Dostaję dokładnie taki sam błąd podczas łączenia się z serwerem SSLv3 za pomocą klienta TLSv1 ... – mata