Skip to content

Commit

Permalink
Simplify SSL socket exceptions in builtin
Browse files Browse the repository at this point in the history
Currently, sockets with SSL exceptions are discarded, except
for http-over-https where we send back an http error response.
For a subset of those exceptions we silient discard them, and
for others we will print out the stack trace.  This patch
updates the code to silient discard all exceptions unless
it is the http-over-https case.
  • Loading branch information
toppk authored and webknjaz committed Sep 29, 2022
1 parent 6d4af62 commit f47dea7
Showing 1 changed file with 6 additions and 54 deletions.
60 changes: 6 additions & 54 deletions cheroot/ssl/builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,68 +272,20 @@ def bind(self, sock):

def wrap(self, sock):
"""Wrap and return the given socket, plus WSGI environ entries."""
EMPTY_RESULT = None, {}
try:
s = self.context.wrap_socket(
sock, do_handshake_on_connect=True, server_side=True,
)
except ssl.SSLZeroReturnError:
# This is almost certainly due to the cherrypy engine
# 'pinging' the socket to assert it's connectable;
# the 'ping' isn't SSL.
return EMPTY_RESULT
return s, self.get_environ(s)
except ssl.SSLError as ex:
if ex.errno == ssl.SSL_ERROR_EOF:
# This is almost certainly due to the cherrypy engine
# 'pinging' the socket to assert it's connectable;
# the 'ping' isn't SSL.
return EMPTY_RESULT
elif ex.errno == ssl.SSL_ERROR_SSL:
if ex.errno == ssl.SSL_ERROR_SSL:
if _assert_ssl_exc_contains(ex, 'http request'):
# The client is speaking HTTP to an HTTPS server.
raise errors.NoSSLError

# Check if it's one of the known errors
# Errors that are caught by PyOpenSSL, but thrown by
# built-in ssl
_block_errors = (
'unknown protocol', 'unknown ca', 'unknown_ca',
'unknown error',
'https proxy request', 'inappropriate fallback',
'wrong version number',
'no shared cipher', 'certificate unknown',
'ccs received early',
'certificate verify failed', # client cert w/o trusted CA
'version too low', # caused by SSL3 connections
'unsupported protocol', # caused by TLS1 connections
)
if _assert_ssl_exc_contains(ex, *_block_errors):
# Accepted error, let's pass
return EMPTY_RESULT
elif _assert_ssl_exc_contains(ex, 'handshake operation timed out'):
# This error is thrown by builtin SSL after a timeout
# when client is speaking HTTP to an HTTPS server.
# The connection can safely be dropped.
return EMPTY_RESULT
raise
except generic_socket_error as exc:
"""It is unclear why exactly this happens.
It's reproducible only with openssl>1.0 and stdlib
:py:mod:`ssl` wrapper.
In CherryPy it's triggered by Checker plugin, which connects
to the app listening to the socket port in TLS mode via plain
HTTP during startup (from the same process).
Ref: https://github.com/cherrypy/cherrypy/issues/1618
"""
is_error0 = exc.args == (0, 'Error')

if is_error0 and IS_ABOVE_OPENSSL10:
return EMPTY_RESULT
raise
return s, self.get_environ(s)
except (generic_socket_error, ssl.SSLZeroReturnError):
pass
# empty result
return None, {}

def get_environ(self, sock):
"""Create WSGI environ entries to be merged into each request."""
Expand Down

0 comments on commit f47dea7

Please sign in to comment.