Note: this code works fine on Ubuntu but not on mac and instead of changing the mac/python settings locally I'm trying to make change to the code so it'll work everywhere..
import ssl
import httplib
httplib.HTTPConnection(server, port, timeout)
but it throws error:
[Errno 1] _ssl.c:503: error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol
now code's not using urllib.request instead using httplib
I want to change the code so it'll take SSLv3 as default protocol, something like this:
ssl.SSLContext(ssl.PROTOCOL_SSLv3)
I looked around and found few links but nothing is working!
Note: The HTTPSConnection constructor allows to pass an ssl context
as argument since python 2.7.9, which should be used in this case.
This answer predates that change and therefore only applies to outdated versions of python.
httplib.HTTPSConnection.connect
just calls ssl.wrap_socket
on the opened socket to initalize a https connection, unfortunately you can't specify any parameters in python2.7 (python3 allows passing the SSLContext
).
If you want to specify the protocol version, you'd need to monkey patch one of these two:
Method 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
This changes the protocol version for all connections made with HTTPSConnection
.
Method 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
This changes the default protocol version for all code that uses wrap_socket
, therefore also affects other libraries.
edit:
Method 3: because httplib actually accesses only wrap_socket
from ssl
, you could also just replace httplib.ssl
with a class providing wrap_socket
. Using functools.partial
makes it very elegant to write this:
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