Skip to content

Commit 299a656

Browse files
authored
fix imports when no TLS is available (move extract_peer_certificate) … (#1560)
* fix imports when no TLS is available (move extract_peer_certificate) - fixes #1559 * update changelog; bump version for hot fix
1 parent 308b5c7 commit 299a656

File tree

3 files changed

+83
-56
lines changed

3 files changed

+83
-56
lines changed

autobahn/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@
2424
#
2525
###############################################################################
2626

27-
__version__ = '22.4.1'
27+
__version__ = '22.4.2'
2828

2929
__build__ = '00000000-0000000'

autobahn/twisted/util.py

Lines changed: 77 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131

3232
from twisted.internet.defer import Deferred
3333
from twisted.internet.address import IPv4Address, UNIXAddress
34-
from twisted.internet.interfaces import ITransport, IProcessTransport, ISSLTransport
34+
from twisted.internet.interfaces import ITransport, IProcessTransport
3535

3636
from autobahn.wamp.types import TransportDetails
3737

@@ -48,6 +48,14 @@
4848
_HAS_IPV6 = False
4949
IPv6Address = type(None)
5050

51+
try:
52+
from twisted.internet.interfaces import ISSLTransport
53+
from twisted.protocols.tls import TLSMemoryBIOProtocol
54+
from OpenSSL.SSL import Connection
55+
_HAS_TLS = True
56+
except ImportError:
57+
_HAS_TLS = False
58+
5159
__all = (
5260
'sleep',
5361
'peer2str',
@@ -116,10 +124,7 @@ def peer2str(transport: Union[ITransport, IProcessTransport]) -> str:
116124
return res
117125

118126

119-
try:
120-
from twisted.protocols.tls import TLSMemoryBIOProtocol
121-
from OpenSSL.SSL import Connection
122-
except ImportError:
127+
if not _HAS_TLS:
123128
def transport_channel_id(transport: object, is_server: bool, channel_id_type: Optional[str] = None) -> Optional[bytes]:
124129
if channel_id_type is None:
125130
return b'\x00' * 32
@@ -189,64 +194,78 @@ def transport_channel_id(transport: object, is_server: bool, channel_id_type: Op
189194
raise NotImplementedError('should not arrive here (unhandled channel_id_type "{}")'.format(channel_id_type))
190195

191196

192-
def extract_peer_certificate(transport: TLSMemoryBIOProtocol) -> Optional[Dict[str, Any]]:
193-
"""
194-
Extract TLS x509 client certificate information from a Twisted stream transport, and
195-
return a dict with x509 TLS client certificate information (if the client provided a
196-
TLS client certificate).
197-
"""
198-
# check if the Twisted transport is a TLSMemoryBIOProtocol
199-
if not (ISSLTransport.providedBy(transport) and hasattr(transport, 'getPeerCertificate')):
200-
return None
197+
if not _HAS_TLS:
198+
def extract_peer_certificate(transport: object) -> Optional[Dict[str, Any]]:
199+
"""
200+
Dummy when no TLS is available.
201201
202-
cert = transport.getPeerCertificate()
203-
if cert:
204-
# extract x509 name components from an OpenSSL X509Name object
205-
def maybe_bytes(_value):
206-
if isinstance(_value, bytes):
207-
return _value.decode('utf8')
208-
else:
209-
return _value
210-
211-
result = {
212-
'md5': '{}'.format(maybe_bytes(cert.digest('md5'))).upper(),
213-
'sha1': '{}'.format(maybe_bytes(cert.digest('sha1'))).upper(),
214-
'sha256': '{}'.format(maybe_bytes(cert.digest('sha256'))).upper(),
215-
'expired': bool(cert.has_expired()),
216-
'hash': maybe_bytes(cert.subject_name_hash()),
217-
'serial': int(cert.get_serial_number()),
218-
'signature_algorithm': maybe_bytes(cert.get_signature_algorithm()),
219-
'version': int(cert.get_version()),
220-
'not_before': maybe_bytes(cert.get_notBefore()),
221-
'not_after': maybe_bytes(cert.get_notAfter()),
222-
'extensions': []
223-
}
202+
:param transport: Ignored.
203+
:return: Always return ``None``.
204+
"""
205+
return None
206+
else:
207+
def extract_peer_certificate(transport: TLSMemoryBIOProtocol) -> Optional[Dict[str, Any]]:
208+
"""
209+
Extract TLS x509 client certificate information from a Twisted stream transport, and
210+
return a dict with x509 TLS client certificate information (if the client provided a
211+
TLS client certificate).
224212
225-
for i in range(cert.get_extension_count()):
226-
ext = cert.get_extension(i)
227-
ext_info = {
228-
'name': '{}'.format(maybe_bytes(ext.get_short_name())),
229-
'value': '{}'.format(maybe_bytes(ext)),
230-
'critical': ext.get_critical() != 0
213+
:param transport: The secure transport from which to extract the peer certificate (if present).
214+
:returns: If the peer provided a certificate, the parsed certificate information set.
215+
"""
216+
# check if the Twisted transport is a TLSMemoryBIOProtocol
217+
if not (ISSLTransport.providedBy(transport) and hasattr(transport, 'getPeerCertificate')):
218+
return None
219+
220+
cert = transport.getPeerCertificate()
221+
if cert:
222+
# extract x509 name components from an OpenSSL X509Name object
223+
def maybe_bytes(_value):
224+
if isinstance(_value, bytes):
225+
return _value.decode('utf8')
226+
else:
227+
return _value
228+
229+
result = {
230+
'md5': '{}'.format(maybe_bytes(cert.digest('md5'))).upper(),
231+
'sha1': '{}'.format(maybe_bytes(cert.digest('sha1'))).upper(),
232+
'sha256': '{}'.format(maybe_bytes(cert.digest('sha256'))).upper(),
233+
'expired': bool(cert.has_expired()),
234+
'hash': maybe_bytes(cert.subject_name_hash()),
235+
'serial': int(cert.get_serial_number()),
236+
'signature_algorithm': maybe_bytes(cert.get_signature_algorithm()),
237+
'version': int(cert.get_version()),
238+
'not_before': maybe_bytes(cert.get_notBefore()),
239+
'not_after': maybe_bytes(cert.get_notAfter()),
240+
'extensions': []
231241
}
232-
result['extensions'].append(ext_info)
233242

234-
for entity, name in [('subject', cert.get_subject()), ('issuer', cert.get_issuer())]:
235-
result[entity] = {}
236-
for key, value in name.get_components():
237-
key = maybe_bytes(key)
238-
value = maybe_bytes(value)
239-
result[entity]['{}'.format(key).lower()] = '{}'.format(value)
243+
for i in range(cert.get_extension_count()):
244+
ext = cert.get_extension(i)
245+
ext_info = {
246+
'name': '{}'.format(maybe_bytes(ext.get_short_name())),
247+
'value': '{}'.format(maybe_bytes(ext)),
248+
'critical': ext.get_critical() != 0
249+
}
250+
result['extensions'].append(ext_info)
240251

241-
return result
252+
for entity, name in [('subject', cert.get_subject()), ('issuer', cert.get_issuer())]:
253+
result[entity] = {}
254+
for key, value in name.get_components():
255+
key = maybe_bytes(key)
256+
value = maybe_bytes(value)
257+
result[entity]['{}'.format(key).lower()] = '{}'.format(value)
258+
259+
return result
242260

243261

244262
def create_transport_details(transport: Union[ITransport, IProcessTransport], is_server: bool) -> TransportDetails:
245263
"""
264+
Create transport details from Twisted transport.
246265
247-
:param transport:
248-
:param is_server:
249-
:return:
266+
:param transport: The Twisted transport to extract information from.
267+
:param is_server: Flag indicating whether this transport side is a "server" (as in TCP server).
268+
:return: Transport details object filled with information from the Twisted transport.
250269
"""
251270
peer = peer2str(transport)
252271

@@ -259,17 +278,20 @@ def create_transport_details(transport: Union[ITransport, IProcessTransport], is
259278
own_tid = threading.get_ident()
260279
own_fd = -1
261280

262-
is_secure = ISSLTransport.providedBy(transport)
263-
if is_secure:
281+
if _HAS_TLS and ISSLTransport.providedBy(transport):
264282
channel_id = {
265283
'tls-unique': transport_channel_id(transport, is_server, 'tls-unique'),
266284
}
267285
channel_type = TransportDetails.CHANNEL_TYPE_TLS
268286
peer_cert = extract_peer_certificate(transport)
287+
is_secure = True
269288
else:
270289
channel_id = {}
271290
channel_type = TransportDetails.CHANNEL_TYPE_TCP
272291
peer_cert = None
292+
is_secure = False
293+
294+
# FIXME: really set a default (websocket)?
273295
channel_framing = TransportDetails.CHANNEL_FRAMING_WEBSOCKET
274296

275297
return TransportDetails(channel_type=channel_type, channel_framing=channel_framing, peer=peer,

docs/changelog.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
Changelog
66
=========
77

8+
22.4.2
9+
------
10+
11+
* fix: can not import autobahn.twisted.util with no-TLS (#1559)
12+
813
22.4.1
914
------
1015

0 commit comments

Comments
 (0)