Files
python-kasa/kasa/transports/sslcontext.py
Teemu R. 2a81f74e9c
Some checks failed
CI / Perform Lint Checks (3.14) (push) Has been cancelled
CodeQL Checks / Analyze (python) (push) Has been cancelled
CI / Python 3.11 on macos-latest (push) Has been cancelled
CI / Python 3.12 on macos-latest (push) Has been cancelled
CI / Python 3.13 on macos-latest (push) Has been cancelled
CI / Python 3.14 on macos-latest (push) Has been cancelled
CI / Python 3.11 on ubuntu-latest (push) Has been cancelled
CI / Python 3.12 on ubuntu-latest (push) Has been cancelled
CI / Python 3.13 on ubuntu-latest (push) Has been cancelled
CI / Python 3.14 on ubuntu-latest (push) Has been cancelled
CI / Python 3.11 on windows-latest (push) Has been cancelled
CI / Python 3.12 on windows-latest (push) Has been cancelled
CI / Python 3.13 on windows-latest (push) Has been cancelled
CI / Python 3.14 on windows-latest (push) Has been cancelled
Consolidate SSL ciphers and use them in SslTransport (#1798)
- Add `kasa/transports/sslcontext.py` with one shared SSL context for
the https transports to avoid copies across transports.
- Use it in `SslTransport`, and convert KLAP and Linkie also to use it.
- Extend Python's default ciphers with the legacy suites instead of
replacing accepted ciphers for future compatibility.
2026-10-14 23:16:56 +02:00

41 lines
1.2 KiB
Python

"""Shared SSL context for the transports talking https to local devices.
Not security sensitive: certificates are not verified.
The extra ciphers exist only for compatibility,
as Python's defaults lack suites older firmware needs.
"""
from __future__ import annotations
import asyncio
import ssl
from functools import cache
LEGACY_CIPHERS = [
"AES256-GCM-SHA384",
"AES256-SHA256",
"AES128-GCM-SHA256",
"AES128-SHA256",
"AES256-SHA",
"AES128-SHA",
"ECDHE-RSA-AES128-SHA",
"ECDHE-RSA-AES256-SHA",
]
@cache
def _create_ssl_context() -> ssl.SSLContext:
"""Return the cached context, blocking on first use."""
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
# Append to the defaults so suites newer firmware needs are not dropped.
default = [cipher["name"] for cipher in context.get_ciphers()]
context.set_ciphers(":".join([*default, *LEGACY_CIPHERS]))
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
return context
async def get_ssl_context() -> ssl.SSLContext:
"""Return the cached context, created in an executor as that blocks."""
return await asyncio.get_running_loop().run_in_executor(None, _create_ssl_context)