@@ -249,8 +249,9 @@ def set_ciphers(self, ciphers):
249249 be selected (because compile-time options or other configuration
250250 forbids use of all the specified ciphers), an SSLError will be raised.
251251 """
252+ cipherBytes = t2b (ciphers )
252253 ret = _lib .wolfSSL_CTX_set_cipher_list (self .native_object ,
253- t2b ( ciphers ))
254+ _ffi . new ( "char[]" , cipherBytes ))
254255
255256 if ret != _SSL_SUCCESS :
256257 raise SSLError ("Unable to set cipher list" )
@@ -259,8 +260,11 @@ def use_sni(self, server_hostname):
259260 """
260261 Sets the SNI hostname, wraps native wolfSSL_CTX_UseSNI()
261262 """
263+
264+ sni = t2b (server_hostname )
265+
262266 ret = _lib .wolfSSL_CTX_UseSNI (self .native_object , 0 ,
263- server_hostname , len (server_hostname ))
267+ sni , len (sni ))
264268
265269 if ret != _SSL_SUCCESS :
266270 raise SSLError ("Unable to set wolfSSL CTX SNI" )
@@ -355,7 +359,7 @@ def __init__(self, sock=None, keyfile=None, certfile=None,
355359 # set options
356360 self .do_handshake_on_connect = do_handshake_on_connect
357361 self .suppress_ragged_eofs = suppress_ragged_eofs
358- self .server_side = server_side
362+ self ._server_side = server_side
359363
360364 # save socket
361365 self ._sock = sock
@@ -421,8 +425,10 @@ def __init__(self, sock=None, keyfile=None, certfile=None,
421425 # match domain name / host name if set in context
422426 if server_hostname is not None :
423427 if self ._context .check_hostname :
428+
429+ sni = _ffi .new ("char[]" , server_hostname .encode ("utf-8" ))
424430 _lib .wolfSSL_check_domain_name (self .native_object ,
425- server_hostname )
431+ sni )
426432
427433 if connected :
428434 try :
@@ -441,13 +447,22 @@ def _release_native_object(self):
441447 _lib .wolfSSL_free (self .native_object )
442448 self .native_object = _ffi .NULL
443449
450+ def pending (self ):
451+ return _lib .wolfSSL_pending (self .native_object )
452+
444453 @property
445454 def context (self ):
446455 """
447456 Returns the context used by this object.
448457 """
449458 return self ._context
450459
460+ def server_side (self ):
461+ """
462+ Returns True for server-side socket, otherwise False.
463+ """
464+ return self ._server_side ;
465+
451466 def dup (self ):
452467 raise NotImplementedError ("Can't dup() %s instances" %
453468 self .__class__ .__name__ )
@@ -468,8 +483,11 @@ def use_sni(self, server_hostname):
468483 """
469484 Sets the SNI hostname, wraps native wolfSSL_UseSNI()
470485 """
486+
487+ sni = t2b (server_hostname )
488+
471489 ret = _lib .wolfSSL_UseSNI (self .native_object , 0 ,
472- server_hostname , len (server_hostname ))
490+ sni , len (sni ))
473491
474492 if ret != _SSL_SUCCESS :
475493 raise SSLError ("Unable to set wolfSSL SNI" )
@@ -502,9 +520,17 @@ def sendall(self, data, flags=0):
502520 sent = 0
503521
504522 while sent < length :
505- sent += self .write (data [sent :])
523+ ret = self .write (data [sent :])
524+ if (ret < 0 ):
525+ err = _lib .wolfSSL_get_error (self .native_object , 0 )
526+ if err == _SSL_ERROR_WANT_WRITE :
527+ raise SSLWantWriteError ()
528+ else :
529+ raise SSLError ("wolfSSL_write error (%d)" % err )
530+
531+ sent += ret
506532
507- return sent
533+ return None
508534
509535 def sendto (self , data , flags_or_addr , addr = None ):
510536 # Ensures not to send unencrypted data trying to use this method
@@ -606,7 +632,7 @@ def shutdown(self, how):
606632 if self .native_object != _ffi .NULL :
607633 _lib .wolfSSL_shutdown (self .native_object )
608634 self ._release_native_object ()
609- socket . shutdown ( self ._sock , how )
635+ self ._sock . shutdown ( how )
610636
611637 def unwrap (self ):
612638 """
@@ -620,22 +646,20 @@ def unwrap(self):
620646 sock_type = self ._sock .type ,
621647 proto = self ._sock .proto ,
622648 fileno = self ._sock .fileno ())
649+
623650 sock .settimeout (self ._sock .gettimeout ())
624651 self ._sock .detach ()
625652
626653 return sock
627654
628- def close (self ):
629- self ._sock .close ()
630-
631655 def do_handshake (self , block = False ): # pylint: disable=unused-argument
632656 """
633657 Perform a TLS/SSL handshake.
634658 """
635659 self ._check_closed ("do_handshake" )
636660 self ._check_connected ()
637661
638- if self .server_side :
662+ if self ._server_side :
639663 ret = _lib .wolfSSL_accept (self .native_object )
640664 else :
641665 ret = _lib .wolfSSL_connect (self .native_object )
@@ -678,7 +702,7 @@ def do_handshake(self, block=False): # pylint: disable=unused-argument
678702 (err , eStr ))
679703
680704 def _real_connect (self , addr , connect_ex ):
681- if self .server_side :
705+ if self ._server_side :
682706 raise ValueError ("can't connect in server-side mode" )
683707
684708 # Here we assume that the socket is client-side, and not
@@ -687,10 +711,10 @@ def _real_connect(self, addr, connect_ex):
687711 raise ValueError ("attempt to connect already-connected SSLSocket!" )
688712
689713 if connect_ex :
690- err = socket . connect_ex ( self ._sock , addr )
714+ err = self ._sock . connect_ex ( addr )
691715 else :
692716 err = 0
693- socket . connect ( self ._sock , addr )
717+ self ._sock . connect ( addr )
694718
695719 if err == 0 :
696720 self ._connected = True
@@ -719,10 +743,10 @@ def accept(self):
719743 containing that new connection wrapped with a server-side secure
720744 channel, and the address of the remote client.
721745 """
722- if not self .server_side :
746+ if not self ._server_side :
723747 raise ValueError ("can't accept in client-side mode" )
724748
725- newsock , addr = socket . accept ( self ._sock )
749+ newsock , addr = self ._sock . accept ( )
726750 newsock = self .context .wrap_socket (
727751 newsock ,
728752 do_handshake_on_connect = self .do_handshake_on_connect ,
@@ -758,6 +782,43 @@ def getpeercert(self, binary_form=False):
758782 return {'subject' : ((('commonName' , x509 .get_subject_cn ()),),),
759783 'subjectAltName' : x509 .get_altnames () }
760784
785+ # The following functions expose functionality of the underlying
786+ # Socket object. These are also expsed through Python's ssl module
787+ # API and are provided here for compatibility.
788+ def close (self ):
789+ self ._sock .close ()
790+
791+ def fileno (self ):
792+ """
793+ Return file descriptor of underlying socket.
794+ """
795+ return self ._sock .fileno ()
796+
797+ def gettimeout (self ):
798+ """
799+ Return the socket timeout of the underlying wrapped socket
800+ """
801+ return self ._sock .gettimeout ()
802+
803+ def settimeout (self , timeout ):
804+ """
805+ Set the timeout on the underlying wrapped socket
806+ """
807+ self ._sock .settimeout (timeout )
808+
809+ def getpeername (self ):
810+ """
811+ Return the remote address that the underlying socket is connected to
812+ """
813+ return self ._sock .getpeername ()
814+
815+ def getsockname (self ):
816+ """
817+ Return the underlying socket's address
818+ """
819+ return self ._sock .getsockname ()
820+
821+
761822
762823def wrap_socket (sock , keyfile = None , certfile = None , server_side = False ,
763824 cert_reqs = CERT_NONE , ssl_version = PROTOCOL_TLS , ca_certs = None ,
0 commit comments