Wrap_socket() Got An Unexpected Keyword Argument 'server_hostname'?
Solution 1:
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.whileTrue:
x = s2.read()
ifnot x:
breakprint(x)
Solution 2:
First connect, then wrap the socket.
import socket, sslsock= socket.create_connection( ('localhost', 443) )
sock = ssl.wrap_socket(sock, ca_certs="./pki/signing-dss-cert.pem", cert_reqs=ssl.CERT_REQUIRED, ssl_version=ssl.PROTOCOL_TLSv1)
In case of python2 I also use the following hack sometimes (because the httplib.HTTPSConnection
documentation says that it doesn't perform any kind of checking on the https server cert):
import urllib, httplib, ssl
PATH = urllib.quote(u'/'.encode('utf-8'))
conn = httplib.HTTPConnection('www.google.com', 443)
conn.connect()
try:
conn.sock = ssl.wrap_socket(conn.sock, cert_reqs=ssl.CERT_REQUIRED, ca_certs=CA_BUNDLE_FILE, ssl_version=VERSION)
conn.request('GET', PATH)
resp = conn.getresponse()
print resp.status
print resp.read()
finally:
conn.close()
Note that if you want to communicate with the server then using a http client is often much easier than playing around with raw sockets.
Solution 3:
My env is:requests==2.7.0, python-2.7.5-34.el7.x86_64, gevent==1.0.2
Change python version to python-2.7.5-18.el7_1.1.x86_64, problem is solved.
on CentOS:
sudo rpm -Uvh --oldpackage python-devel-2.7.5-18.el7_1.1.x86_64.rpm python-libs-2.7.5-18.el7_1.1.x86_64.rpm python-2.7.5-18.el7_1.1.x86_64.rpm
pakages can search on google.
Post a Comment for "Wrap_socket() Got An Unexpected Keyword Argument 'server_hostname'?"