Skip to content

Commit

Permalink
Fixed TypeError when TLS handshake fails with truststore SSLContext (#…
Browse files Browse the repository at this point in the history
…801)

Fixes #795.

(cherry picked from commit ede2029)
  • Loading branch information
agronholm committed Oct 13, 2024
1 parent 4cb89a5 commit bf130dc
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 3 deletions.
3 changes: 3 additions & 0 deletions docs/versionhistory.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ This library adheres to `Semantic Versioning 2.0 <http://semver.org/>`_.
- Fixed an async fixture's ``self`` being different than the test's ``self`` in
class-based tests (`#633 <https://github.com/agronholm/anyio/issues/633>`_)
(PR by @agronholm and @graingert)
- Fixed ``TypeError`` with ``TLSStream`` on Windows when a certificate verification
error occurs when using a `truststore <https://github.com/sethmlarson/truststore>`_
SSL certificate (`#795 <https://github.com/agronholm/anyio/issues/795>`_)

**4.6.0**

Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ test = [
"pytest >= 7.0",
"pytest-mock >= 3.6.1",
"trustme",
"truststore >= 0.9.1; python_version >= '3.10'",
"""\
uvloop >= 0.21.0b1; platform_python_implementation == 'CPython' \
and platform_system != 'Windows'\
Expand Down
5 changes: 2 additions & 3 deletions src/anyio/streams/tls.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,8 @@ async def _call_sslobject_method(
except ssl.SSLError as exc:
self._read_bio.write_eof()
self._write_bio.write_eof()
if (
isinstance(exc, ssl.SSLEOFError)
or "UNEXPECTED_EOF_WHILE_READING" in exc.strerror
if isinstance(exc, ssl.SSLEOFError) or (
exc.strerror and "UNEXPECTED_EOF_WHILE_READING" in exc.strerror
):
if self.standard_compatible:
raise BrokenResourceError from exc
Expand Down
28 changes: 28 additions & 0 deletions tests/streams/test_tls.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,34 @@ async def test_default_context_ignore_unexpected_eof_flag_off(
send1.close()
receive1.close()

async def test_truststore_ssl(
self, request: pytest.FixtureRequest, server_context: ssl.SSLContext
) -> None:
# This test is only expected to fail on Windows without the associated patch
def serve_sync() -> None:
with server_sock, pytest.raises(ssl.SSLEOFError):
server_sock.accept()

# We deliberately skip making the client context trust the server context
truststore = pytest.importorskip("truststore")
client_context = truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT)

server_sock = server_context.wrap_socket(
socket.socket(), server_side=True, suppress_ragged_eofs=True
)
server_sock.settimeout(1)
server_sock.bind(("127.0.0.1", 0))
server_sock.listen()
server_thread = Thread(target=serve_sync, daemon=True)
server_thread.start()
request.addfinalizer(server_thread.join)

async with await connect_tcp(*server_sock.getsockname()) as stream:
with pytest.raises(ssl.SSLCertVerificationError):
await TLSStream.wrap(
stream, hostname="localhost", ssl_context=client_context
)


class TestTLSListener:
async def test_handshake_fail(
Expand Down

0 comments on commit bf130dc

Please sign in to comment.