...
 
Commits (1)
  • Kirill Smelkov's avatar
    ssl: Don't ignore non-ragged EOF · bca99c55
    Kirill Smelkov authored
    Testing NEO/go client wrt NEO/py server revealed a bug in NEO/py SSL
    handling: proper non-ragged EOF from a peer is ignored, and so leads to
    hang in infinite loop inside _SSL.receive with read_buf memory growing
    indefinitely. Details are below:
    
    NEO/py wraps raw sockets with
    
    	ssl.wrap_socket(suppress_ragged_eofs=False)
    
    which instructs SSL layer to convert unexpected EOF when receiving a TLS
    record into SSLEOFError exception. However when remote peer properly
    closes its side of the connection, socket.read() still returns b'' to
    report non-ragged regular EOF:
    
    https://github.com/python/cpython/blob/v2.7.18/Lib/ssl.py#L630-L650
    
    The code was handling SSLEOFError but not b'' return from socket recv.
    Thus after NEO/go client was disconnecting and properly closing its side
    of the connection, the code started to loop indefinitely in _SSL.receive
    under `while 1` with  b'' returned by self.socket.recv() appended to
    read_buf again and again.
    
    -> Fix it by detecting non-ragged EOF as well and, similarly to how
    SSLEOFError is handled, converting them into self._error('recv', None).
    bca99c55
......@@ -278,7 +278,12 @@ class _SSL:
def receive(self, read_buf):
try:
while 1:
read_buf.append(self.socket.recv(4096))
data = self.socket.recv(4096)
if data == b'':
# non-ragged EOF (peer properly closed its side of connection)
self._error('recv', None)
return
read_buf.append(data)
except ssl.SSLWantReadError:
pass
except socket.error, e:
......