The patch you're mentioning is for Python 3.2, and you're using Python 2.7. Issue 5639 also seems to indicate there is no plan to back-port SNI support for Python 2.7.
You could wrap the socket with pyOpenSSL instead (its Connection
class has a set_tlsext_host_name
since version 0.13. (I'm not sure which version comes with Debian 7.3, you might want to set up a virtualenv and upgrade to a newer version locally, if needed.)
There is an SNI example is the pyOpenSSL repository.
If you want your usage of wrap_socket
to be more compatible with the trick were you replace the value of sock
in an httplib
connection, you could have a look at how urllib3 does this with pyOpenSSL. Essentially, it creates an OpenSSL.SSL.Connection
from an existing socket, but since that connection isn't compatible with a socket, it wraps it into a class that implements the required method.
(By the way, in Python 2.7, urllib
, urllib2
and httpconnection
don't do any certificate verification at all, unless you implement it yourself by wrapping their sockets.)
EDIT:
Here is a version of your code that should work with Python 3.2. Unfortunately, the server_name
parameter isn't in the plain ssl.wrap_socket
, only in SSLContext.wrap_socket
, but you can use SSLSocket
directly.
import socket
import ssl
CA_BUNDLE_FILE="/etc/ssl/certs/ca-certificates.crt"
HOST = "sni.velox.ch"
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s2 = ssl.SSLSocket(sock=s1, ca_certs=CA_BUNDLE_FILE,
cert_reqs=ssl.CERT_REQUIRED,
ssl_version=ssl.PROTOCOL_TLSv1,
server_hostname=HOST)
s2.connect((HOST, 443))
s2.send(bytes("GET / HTTP/1.1\n", "UTF-8"))
# This might need to be modified when using another port
s2.send(bytes("Host: %s\n" % (HOST,), "UTF-8"))
s2.send(bytes("\n", "UTF-8"))
# Certainly not the best way to read the response, but it works.
while True:
x = s2.read()
if not x:
break
print(x)