fix string decoding, implement recv_into(), add alert history

pull/8/head
Chris Conlon 2019-01-18 15:12:35 -08:00
parent 8ada6e4d3a
commit cf75110fd9
2 changed files with 75 additions and 43 deletions

View File

@ -94,14 +94,7 @@ class WolfSSLX509(object):
if cnPtr == _ffi.NULL:
return ''
cn = _ffi.string(cnPtr)
if _PY3:
if isinstance(cn, bytes):
cn = cn.decode("utf-8")
else:
if isinstance(cn, unicode):
cn = cn.encode("utf-8")
cn = _ffi.string(cnPtr).decode("ascii")
return cn
@ -110,7 +103,7 @@ class WolfSSLX509(object):
if (sanPtr == _ffi.NULL):
return None
san = _ffi.string(sanPtr)
san = _ffi.string(sanPtr).decode("ascii")
return san
@ -284,6 +277,11 @@ class SSLContext(object):
private key in.
The password parameter is not supported yet.
wolfSSL does not support loading a certificate file that contains
both the certificate AND private key. In this case, users should
split them into two separate files and load using the certfile
and keyfile parameters, respectively.
"""
if password is not None:
@ -397,35 +395,6 @@ class SSLSocket(object):
if server_hostname is not None:
self._context.use_sni(server_hostname)
# preparing socket
if sock is not None:
# Can't use sock.type as other flags (such as SOCK_NONBLOCK) get
# mixed in.
if sock.getsockopt(SOL_SOCKET, SO_TYPE) != SOCK_STREAM:
raise NotImplementedError("only stream sockets are supported")
if _PY3:
socket.__init__(self._sock,
family=sock.family,
type=sock.type,
proto=sock.proto,
fileno=sock.fileno())
else:
socket.__init__(
self._sock, _sock=sock._sock) # pylint: disable=protected-access
self._sock.settimeout(sock.gettimeout())
if _PY3:
sock.detach()
elif fileno is not None:
socket.__init__(self._sock, fileno=fileno)
else:
socket.__init__(self._sock, family=family, type=sock_type,
proto=proto)
# see if we are connected
try:
self._sock.getpeername()
@ -584,8 +553,36 @@ class SSLSocket(object):
return self.read(length=length)
def recv_into(self, buffer, nbytes=None, flags=0):
raise NotImplementedError("recv_into not allowed on instances "
"of %s" % self.__class__)
"""
Read nbytes bytes and place into buffer. If nbytes is 0, read up
to full size of buffer.
"""
self._check_closed("read")
self._check_connected()
if buffer is None:
raise ValueError("buffer cannot be None")
if nbytes is None:
nbytes = len(buffer)
else:
nbytes = min(len(buffer), nbytes)
if nbytes == 0:
return 0
data = _ffi.from_buffer(buffer)
length = _lib.wolfSSL_read(self.native_object, data, nbytes)
if length < 0:
err = _lib.wolfSSL_get_error(self.native_object, 0)
if err == _SSL_ERROR_WANT_READ:
raise SSLWantReadError()
else:
raise SSLError("wolfSSL_read error (%d)" % err)
return length
def recvfrom(self, length=1024, flags=0):
# Ensures not to receive encrypted data trying to use this method
@ -651,7 +648,8 @@ class SSLSocket(object):
raise SSLWantWriteError()
else:
eBuf = _ffi.new("char[80]")
eStr = _ffi.string(_lib.wolfSSL_ERR_error_string(err, eBuf))
eStr = _ffi.string(_lib.wolfSSL_ERR_error_string(err,
eBuf)).decode("ascii")
if 'ASN no signer error to confirm' in eStr or err is -188:
# Some Python ssl consumers explicitly check error message
@ -659,8 +657,25 @@ class SSLSocket(object):
raise SSLError("do_handshake failed with error %d, "
"certificate verify failed" % err)
raise SSLError("do_handshake failed with error %d: %s" %
(err, eStr))
# get alert code and string to put in exception msg
alertHistoryPtr = _ffi.new("WOLFSSL_ALERT_HISTORY*")
alertRet = _lib.wolfSSL_get_alert_history(self.native_object,
alertHistoryPtr)
if alertRet == _SSL_SUCCESS:
alertHistory = alertHistoryPtr[0]
code = alertHistory.last_rx.code
alertDesc = _lib.wolfSSL_alert_type_string_long(code)
if alertDesc != _ffi.NULL:
alertStr = _ffi.string(alertDesc).decode("ascii")
else:
alertStr = ''
raise SSLError("do_handshake failed with error %d: %s. "
"alert (%d): %s" %
(err, eStr, code, alertStr))
else:
raise SSLError("do_handshake failed with error %d: %s" %
(err, eStr))
def _real_connect(self, addr, connect_ex):
if self.server_side:

View File

@ -41,6 +41,20 @@ ffi.set_source(
ffi.cdef(
"""
/**
* Structs
*/
typedef struct WOLFSSL_ALERT {
int code;
int level;
} WOLFSSL_ALERT;
typedef struct WOLFSSL_ALERT_HISTORY {
WOLFSSL_ALERT last_rx;
WOLFSSL_ALERT last_tx;
} WOLFSSL_ALERT_HISTORY;
/**
* Types
*/
@ -104,6 +118,9 @@ ffi.cdef(
void* wolfSSL_get_peer_certificate(void*);
int wolfSSL_UseSNI(void*, unsigned char, const void*, unsigned short);
int wolfSSL_check_domain_name(void*, const char*);
int wolfSSL_get_alert_history(void*, WOLFSSL_ALERT_HISTORY*);
char* wolfSSL_alert_type_string_long(int);
char* wolfSSL_alert_desc_string_long(int);
/**
* WOLFSSL_X509 functions