wrap SNI for urllib3, fix debug wrappers, additional WANT_READ/WRITE checks

pull/8/head
Chris Conlon 2018-12-26 12:48:07 -08:00
parent 48fefc2a80
commit fb42244d31
4 changed files with 48 additions and 12 deletions

View File

@ -61,10 +61,22 @@ _VERIFY_MODE_LIST = [CERT_NONE, CERT_REQUIRED]
_SSL_SUCCESS = 1
_SSL_FILETYPE_PEM = 1
_SSL_ERROR_WANT_READ = 2
_SSL_ERROR_WANT_WRITE = 3
_PY3 = sys.version_info[0] == 3
class WolfSSL(object):
@classmethod
def enable_debug(self):
_lib.wolfSSL_Debugging_ON()
@classmethod
def disable_debug(self):
_lib.wolfSSL_Debugging_OFF()
class WolfSSLX509(object):
"""
A WolfSSLX509 represents a X.509 certificate extracted from an SSL/TLS
@ -85,10 +97,10 @@ class WolfSSLX509(object):
cn = _ffi.string(cnPtr)
if _PY3:
if isinstance(cn, binary_type):
if isinstance(cn, bytes):
cn = cn.decode("utf-8")
else:
if isinstance(cn, text_type):
if isinstance(cn, unicode):
cn = cn.encode("utf-8")
return cn
@ -181,7 +193,18 @@ class SSLContext(object):
t2b(ciphers))
if ret != _SSL_SUCCESS:
raise SSLError("Unnable to set cipher list")
raise SSLError("Unable to set cipher list")
def use_sni(self, server_hostname):
"""
Sets the SNI hostname, wraps native wolfSSL_CTX_UseSNI()
"""
ret = _lib.wolfSSL_CTX_UseSNI(self.native_object, 0,
server_hostname, len(server_hostname))
if ret != _SSL_SUCCESS:
raise SSLError("Unable to set wolfSSL CTX SNI")
def load_cert_chain(self, certfile, keyfile=None, password=None):
"""
@ -394,6 +417,16 @@ class SSLSocket(object):
# EAGAIN.
self._sock.getpeername()
def use_sni(self, server_hostname):
"""
Sets the SNI hostname, wraps native wolfSSL_UseSNI()
"""
ret = _lib.wolfSSL_UseSNI(self.native_object, 0,
server_hostname, len(server_hostname))
if ret != _SSL_SUCCESS:
raise SSLError("Unable to set wolfSSL SNI")
def write(self, data):
"""
Write DATA to the underlying secure channel.
@ -533,7 +566,13 @@ class SSLSocket(object):
ret = _lib.wolfSSL_connect(self.native_object)
if ret != _SSL_SUCCESS:
raise SSLError("do_handshake failed with error %d" % ret)
err = _lib.wolfSSL_get_error(self.native_object, 0)
if err == _SSL_ERROR_WANT_READ:
raise SSLWantReadError()
elif err == _SSL_ERROR_WANT_WRITE:
raise SSLWantWriteError()
else:
raise SSLError("do_handshake failed with error %d" % err)
def _real_connect(self, addr, connect_ex):
if self.server_side:

View File

@ -84,6 +84,7 @@ ffi.cdef(
int wolfSSL_CTX_load_verify_locations(void*, const char*, const char*);
int wolfSSL_CTX_load_verify_buffer(void*, const unsigned char*, long,int);
int wolfSSL_CTX_use_certificate_chain_file(void*, const char *);
int wolfSSL_CTX_UseSNI(void*, unsigned char, const void*, unsigned short);
/**
* SSL/TLS Session functions
@ -100,6 +101,7 @@ ffi.cdef(
int wolfSSL_read(void*, void*, int);
int wolfSSL_shutdown(void*);
void* wolfSSL_get_peer_certificate(void*);
int wolfSSL_UseSNI(void*, unsigned char, const void*, unsigned short);
/**
* WOLFSSL_X509 functions

View File

@ -124,6 +124,9 @@ def make_flags(prefix):
# keep peer cert
cflags.append("-DKEEP_PEER_CERT")
# urllib3 requires SNI
flags.append("--enable-tlsx")
joined_flags = " ".join(flags)
joined_cflags = " ".join(cflags)

View File

@ -46,14 +46,6 @@ def _native_free(native_object, dynamic_type):
_lib.wolfSSL_Free(native_object, _ffi.NULL, dynamic_type)
def enable_debug():
_lib.wolfSSL_Debugging_ON()
def disable_debug():
_lib.wolfSSL_Debugging_OFF()
class WolfSSLMethod(object): # pylint: disable=too-few-public-methods
"""
An SSLMethod holds SSL-related configuration options such as