Skip to content
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

Fix secure connections with new openssl #69

Merged
merged 1 commit into from
May 4, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 22 additions & 8 deletions elkm1_lib/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from __future__ import annotations

import ssl
from functools import cache

TLS_VERSIONS = {
# Unfortunately M1XEP does not support auto-negotiation for TLS
Expand All @@ -24,6 +25,26 @@ def url_scheme_is_secure(url: str) -> bool:
return scheme.startswith("elks")


@cache
def ssl_context_for_scheme(scheme: str) -> ssl.SSLContext:
"""Create an SSL context for the given scheme.

Since ssl context is expensive to create, cache it
for future use since we only have a few schemes.
"""
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS)
if tls := TLS_VERSIONS.get(scheme):
ssl_context.minimum_version = tls
ssl_context.maximum_version = tls

ssl_context.set_ciphers(
"DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK"
)
# ssl.OP_LEGACY_SERVER_CONNECT is only available in Python 3.12a4+
ssl_context.options |= getattr(ssl, "OP_LEGACY_SERVER_CONNECT", 0x4)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are stuck with a getattr here since python/cpython#89051 the choice was made not to backport the new constant

return ssl_context


def parse_url(url: str) -> tuple[str, str, int, ssl.SSLContext | None]:
"""Parse a Elk connection string"""
scheme, dest = url.split("://")
Expand All @@ -33,14 +54,7 @@ def parse_url(url: str) -> tuple[str, str, int, ssl.SSLContext | None]:
host, port = dest.split(":") if ":" in dest else (dest, "2101")
elif TLS_VERSIONS.get(scheme):
host, port = dest.split(":") if ":" in dest else (dest, "2601")
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS)
if tls := TLS_VERSIONS.get(scheme):
ssl_context.minimum_version = tls
ssl_context.maximum_version = tls

ssl_context.set_ciphers(
"DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK"
)
ssl_context = ssl_context_for_scheme(scheme)
scheme = "elks"
elif scheme == "serial":
host, port = dest.split(":") if ":" in dest else (dest, "115200")
Expand Down