-
Notifications
You must be signed in to change notification settings - Fork 0
Can't get coverage for ssl.SSLZeroReturnError
#31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I tried to look into this at some point, and I believe that this error
actually does not exist anymore, but I don't remember the source of this
claim.
…On Thu, Apr 11, 2024 at 3:48 PM Facundo Tuesca ***@***.***> wrote:
Our OpenSSLTLSSocket::recv method handles the SSLZeroReturnError
exception on socket.recv by returning zero bytes. However, I have been
unable to trigger that error (in order to get coverage for (2)):
def recv(self, bufsize: int) -> bytes:
"""Receive data from the socket. The return value is a bytes object representing the data received. Should not work before the handshake is completed."""
try:
return self._socket.recv(bufsize) # (1)
except ssl.SSLZeroReturnError:
return b"" # (2)
except Exception:
with _error_converter():
raise
The ssl docs
<https://docs.python.org/3/library/ssl.html#ssl.SSLZeroReturnError> say:
*exception* ssl.*SSLZeroReturnError*
A subclass of SSLError
<https://docs.python.org/3/library/ssl.html#ssl.SSLError> raised when
trying to read or write and the SSL connection has been closed cleanly.
Note that this doesn’t mean that the underlying transport (read TCP) has
been closed.
I have tried creating a test and having our ThreadedEchoServer close its
client socket (closing the connection cleanly), and then attempting a
recv() on the client side, but the corresponding recv() call on (1)
returns b"" without raising an exception.
Following that call, it ends up in the following read() function in the
ssl module (link
<https://github.com/python/cpython/blob/a2ae84726b8b46e6970ae862244dad1a82cf5d19/Lib/ssl.py#L1130-L1149>
):
def read(self, len=1024, buffer=None):
"""Read up to LEN bytes and return them. Return zero-length string on EOF."""
self._checkClosed()
if self._sslobj is None:
raise ValueError("Read on closed or unwrapped SSL socket.")
try:
if buffer is not None:
return self._sslobj.read(len, buffer)
else:
return self._sslobj.read(len)
except SSLError as x: # (3)
if x.args[0] == SSL_ERROR_EOF and self.suppress_ragged_eofs:
if buffer is not None:
return 0
else:
return b''
else:
raise
The read call that occurs in the test mentioned above (after the server
closed the corresponding socket), results in an SSLError exception
handled by (3). The first if ends up being True, and b"" is returned. If,
on the other hand, we set
suppress_ragged_eofs to False when wrapping the socket, an exception is
re-raised, but that exception is UNEXPECTED_EOF_WHILE_READING (not
SSLZeroReturnError, which is the one we're looking for).
Any ideas of why we're not getting the expected exception?
cc @jvdprng <https://github.com/jvdprng> @woodruffw
<https://github.com/woodruffw>
—
Reply to this email directly, view it on GitHub
<#31>, or unsubscribe
<https://github.com/notifications/unsubscribe-auth/A37KBPQGYRYMPYXLPSWKTZTY42IDXAVCNFSM6AAAAABGCLCIJ2VHI2DSMVQWIX3LMV43ASLTON2WKOZSGIZTONZXGI2DOMI>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
--
Joop van de Pol
Security Consultant | Trail of Bits
trailofbits.com
|
OK, I tried to look into the Python If we want to shut down the connection more gracefully, we should call Anyway, if the server |
Oh, it does count as |
So, to conclude, the OpenSSL docs say
Furthermore, for
However, even with
So I think that even with non-compliant peers, it is not possible to trigger this condition in this version of the library. |
By the way, I believe the |
@jvdprng thanks for looking into it! I also spent some time trying to trigger it (without success), but while doing so I also realized that the tlslib.py/src/tlslib/stdlib.py Lines 379 to 384 in 4b15bd2
is actually making it impossible to get a tlslib.py/src/tlslib/stdlib.py Lines 62 to 63 in 4b15bd2
In other words, this test passes since the exception will be ignored: def test_hello(self):
with stdlib._error_converter(ignore_filter=ssl.SSLZeroReturnError):
raise ssl.SSLZeroReturnError() (not that this matters much, since even after removing the |
Yeah, I think the point of the
|
Although in another place the tlslib.py/src/tlslib/stdlib.py Lines 398 to 401 in 4b15bd2
So now I don't know what the original point of this |
To me the second meaning (ignoring and not re-raising the exception) makes more sense, since I don't understand why would you want to have the first meaning (re-raising the exception in |
Solved by #38 |
By playing around with the
I'm planning to restore handling of this error by the shim and ensuring test coverage. |
Our
OpenSSLTLSSocket::recv
method handles theSSLZeroReturnError
exception onsocket.recv
by returning zero bytes. However, I have been unable to trigger that error (in order to get coverage for(2)
):The
ssl
docs say:I have tried creating a test and having our
ThreadedEchoServer
close its client socket (closing the connection cleanly), and then attempting arecv()
on the client side, but the correspondingrecv()
call on(1)
returnsb""
without raising an exception.Following that call, it ends up in the following
read()
function in thessl
module (link):The
read
call that occurs in the test mentioned above (after the server closed the corresponding socket), results in anSSLError
exception handled by(3)
. The firstif
ends up beingTrue
, andb""
is returned. If, on the other hand, we setsuppress_ragged_eofs
toFalse
when wrapping the socket, an exception is re-raised, but that exception isUNEXPECTED_EOF_WHILE_READING
(notSSLZeroReturnError
, which is the one we're looking for).Any ideas of why we're not getting the expected exception?
cc @jvdprng @woodruffw
The text was updated successfully, but these errors were encountered: