@@ -94,14 +94,7 @@ def get_subject_cn(self):
9494 if cnPtr == _ffi .NULL :
9595 return ''
9696
97- cn = _ffi .string (cnPtr )
98-
99- if _PY3 :
100- if isinstance (cn , bytes ):
101- cn = cn .decode ("utf-8" )
102- else :
103- if isinstance (cn , unicode ):
104- cn = cn .encode ("utf-8" )
97+ cn = _ffi .string (cnPtr ).decode ("ascii" )
10598
10699 return cn
107100
@@ -110,7 +103,7 @@ def get_next_altname(self):
110103 if (sanPtr == _ffi .NULL ):
111104 return None
112105
113- san = _ffi .string (sanPtr )
106+ san = _ffi .string (sanPtr ). decode ( "ascii" )
114107
115108 return san
116109
@@ -284,6 +277,11 @@ def load_cert_chain(self, certfile, keyfile=None, password=None):
284277 private key in.
285278
286279 The password parameter is not supported yet.
280+
281+ wolfSSL does not support loading a certificate file that contains
282+ both the certificate AND private key. In this case, users should
283+ split them into two separate files and load using the certfile
284+ and keyfile parameters, respectively.
287285 """
288286
289287 if password is not None :
@@ -397,35 +395,6 @@ def __init__(self, sock=None, keyfile=None, certfile=None,
397395 if server_hostname is not None :
398396 self ._context .use_sni (server_hostname )
399397
400- # preparing socket
401- if sock is not None :
402- # Can't use sock.type as other flags (such as SOCK_NONBLOCK) get
403- # mixed in.
404- if sock .getsockopt (SOL_SOCKET , SO_TYPE ) != SOCK_STREAM :
405- raise NotImplementedError ("only stream sockets are supported" )
406-
407- if _PY3 :
408- socket .__init__ (self ._sock ,
409- family = sock .family ,
410- type = sock .type ,
411- proto = sock .proto ,
412- fileno = sock .fileno ())
413- else :
414- socket .__init__ (
415- self ._sock , _sock = sock ._sock ) # pylint: disable=protected-access
416-
417- self ._sock .settimeout (sock .gettimeout ())
418-
419- if _PY3 :
420- sock .detach ()
421-
422- elif fileno is not None :
423- socket .__init__ (self ._sock , fileno = fileno )
424-
425- else :
426- socket .__init__ (self ._sock , family = family , type = sock_type ,
427- proto = proto )
428-
429398 # see if we are connected
430399 try :
431400 self ._sock .getpeername ()
@@ -584,8 +553,36 @@ def recv(self, length=1024, flags=0):
584553 return self .read (length = length )
585554
586555 def recv_into (self , buffer , nbytes = None , flags = 0 ):
587- raise NotImplementedError ("recv_into not allowed on instances "
588- "of %s" % self .__class__ )
556+ """
557+ Read nbytes bytes and place into buffer. If nbytes is 0, read up
558+ to full size of buffer.
559+ """
560+ self ._check_closed ("read" )
561+ self ._check_connected ()
562+
563+ if buffer is None :
564+ raise ValueError ("buffer cannot be None" )
565+
566+ if nbytes is None :
567+ nbytes = len (buffer )
568+ else :
569+ nbytes = min (len (buffer ), nbytes )
570+
571+ if nbytes == 0 :
572+ return 0
573+
574+ data = _ffi .from_buffer (buffer )
575+ length = _lib .wolfSSL_read (self .native_object , data , nbytes )
576+
577+ if length < 0 :
578+ err = _lib .wolfSSL_get_error (self .native_object , 0 )
579+ if err == _SSL_ERROR_WANT_READ :
580+ raise SSLWantReadError ()
581+ else :
582+ raise SSLError ("wolfSSL_read error (%d)" % err )
583+
584+ return length
585+
589586
590587 def recvfrom (self , length = 1024 , flags = 0 ):
591588 # Ensures not to receive encrypted data trying to use this method
@@ -651,16 +648,34 @@ def do_handshake(self, block=False): # pylint: disable=unused-argument
651648 raise SSLWantWriteError ()
652649 else :
653650 eBuf = _ffi .new ("char[80]" )
654- eStr = _ffi .string (_lib .wolfSSL_ERR_error_string (err , eBuf ))
651+ eStr = _ffi .string (_lib .wolfSSL_ERR_error_string (err ,
652+ eBuf )).decode ("ascii" )
655653
656654 if 'ASN no signer error to confirm' in eStr or err is - 188 :
657655 # Some Python ssl consumers explicitly check error message
658656 # for 'certificate verify failed'
659657 raise SSLError ("do_handshake failed with error %d, "
660658 "certificate verify failed" % err )
661659
662- raise SSLError ("do_handshake failed with error %d: %s" %
663- (err , eStr ))
660+ # get alert code and string to put in exception msg
661+ alertHistoryPtr = _ffi .new ("WOLFSSL_ALERT_HISTORY*" )
662+ alertRet = _lib .wolfSSL_get_alert_history (self .native_object ,
663+ alertHistoryPtr )
664+ if alertRet == _SSL_SUCCESS :
665+ alertHistory = alertHistoryPtr [0 ]
666+ code = alertHistory .last_rx .code
667+ alertDesc = _lib .wolfSSL_alert_type_string_long (code )
668+ if alertDesc != _ffi .NULL :
669+ alertStr = _ffi .string (alertDesc ).decode ("ascii" )
670+ else :
671+ alertStr = ''
672+
673+ raise SSLError ("do_handshake failed with error %d: %s. "
674+ "alert (%d): %s" %
675+ (err , eStr , code , alertStr ))
676+ else :
677+ raise SSLError ("do_handshake failed with error %d: %s" %
678+ (err , eStr ))
664679
665680 def _real_connect (self , addr , connect_ex ):
666681 if self .server_side :
0 commit comments