Hoernchen has uploaded this change for review.
osmo-smdpp: fix Twisted ALPN issues with pyOpenSSL
pyOpenSSL >= 25.0.0 makes a Context immutable once it has been used and
raises. Downgrading pyOpenSSL is not a fix either: < 25 does not import
against recent cryptography.
This server only speaks HTTP/1.1 anway so ALPN negotiation is unused
and this can be hotpatched for affected versions.
Change-Id: I5d53216f24a20625d12f0757015c19fe341303b9
---
M osmo-smdpp.py
1 file changed, 46 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/48/43548/1
diff --git a/osmo-smdpp.py b/osmo-smdpp.py
index 2a8e478..8120b0f 100755
--- a/osmo-smdpp.py
+++ b/osmo-smdpp.py
@@ -136,6 +136,52 @@
import logging # noqa: E402
logger = logging.getLogger(__name__)
+
+def _disable_twisted_alpn_if_incompatible():
+ """Twisted <-> pyOpenSSL TLS compatibility guard applied at import.
+
+ Twisted TLSMemoryBIOFactory applies ALPN by setting the 'select' callback
+ on the SSL Context after it has already created a Connection from that
+ Context (_createConnection -> _applyProtocolNegotiation).
+ pyOpenSSL >= 25.0.0 makes a Context immutable once it has been used and
+ raises, which aborts every inbound TLS handshake, client sees unexpected-EOF
+ / decode_error that looks like a cert/cipher problem but is not.
+ pyOpenSSL < 25 does not import against recent cryptography, so downgrading
+ it is not a fix.
+
+ This server only speaks HTTP/1.1 anyway, so ALPN negotiation is not
+ needed.
+ """
+ def _major(v):
+ import re
+ m = re.match(r'\d+', (v or '').strip())
+ return int(m.group()) if m else 0
+
+ try:
+ import OpenSSL
+ except Exception:
+ return # no pyOpenSSL ???
+ pyossl_ver = getattr(OpenSSL, '__version__', '0')
+ if _major(pyossl_ver) < 25:
+ return # pre-25 pyOpenSSL allows mutating a used Context
+
+ try:
+ import twisted
+ from twisted.protocols import tls
+ except Exception:
+ return
+ factory = getattr(tls, 'TLSMemoryBIOFactory', None)
+ if factory is None or not hasattr(factory, '_applyProtocolNegotiation'):
+ return # Twisted already fixed
+
+ factory._applyProtocolNegotiation = lambda self, connection: None
+ logger.warning("Disabled Twisted ALPN negotiation: Twisted %s + "
+ "pyOpenSSL %s are incompatible for it",
+ getattr(twisted, '__version__', '?'), pyossl_ver)
+
+
+_disable_twisted_alpn_if_incompatible()
+
# HACK: make this configurable
DATA_DIR = './smdpp-data'
HOSTNAME = 'testsmdpplus1.example.com' # must match certificates!
To view, visit change 43548. To unsubscribe, or for help writing mail filters, visit settings.