Mercurial > libervia-backend
comparison sat/core/patches.py @ 3044:691283719bb2
core (patches): updated TLS patches:
- updated patches to handle TLS after implementation in Twisted 19.7.0. A patch is still
needed for Wokkel.
- minimum required version of Twisted is now 19.7.0
author | Goffi <goffi@goffi.org> |
---|---|
date | Tue, 01 Oct 2019 22:49:10 +0200 |
parents | ab2696e34d29 |
children | 524856bd7b19 |
comparison
equal
deleted
inserted
replaced
3043:3df611adb598 | 3044:691283719bb2 |
---|---|
1 import copy | 1 import copy |
2 from twisted.words.protocols.jabber import xmlstream, sasl, client as tclient, jid | 2 from twisted.words.protocols.jabber import xmlstream, sasl, client as tclient, jid |
3 from twisted.internet import ssl | |
4 from wokkel import client | 3 from wokkel import client |
5 from sat.core.constants import Const as C | 4 from sat.core.constants import Const as C |
6 from sat.core.log import getLogger | 5 from sat.core.log import getLogger |
7 | 6 |
8 log = getLogger(__name__) | 7 log = getLogger(__name__) |
9 | 8 |
10 """This module apply monkey patches to Twisted and Wokkel | 9 """This module applies monkey patches to Twisted and Wokkel |
11 First part handle certificate validation during XMPP connectionand are temporary | 10 First part handle certificate validation during XMPP connectionand are temporary |
12 (until merged upstream). | 11 (until merged upstream). |
13 Second part add a trigger point to send and onElement method of XmlStream | 12 Second part add a trigger point to send and onElement method of XmlStream |
14 """ | 13 """ |
15 | 14 |
16 | 15 |
17 ## certificate validation patches | 16 ## certificate validation patches |
18 | 17 |
19 class TLSInitiatingInitializer(xmlstream.TLSInitiatingInitializer): | |
20 check_certificate = True | |
21 | |
22 def onProceed(self, obj): | |
23 self.xmlstream.removeObserver('/failure', self.onFailure) | |
24 trustRoot = ssl.platformTrust() if self.check_certificate else None | |
25 ctx = ssl.CertificateOptions(trustRoot=trustRoot) | |
26 self.xmlstream.transport.startTLS(ctx) | |
27 self.xmlstream.reset() | |
28 self.xmlstream.sendHeader() | |
29 self._deferred.callback(xmlstream.Reset) | |
30 | |
31 | 18 |
32 class XMPPClient(client.XMPPClient): | 19 class XMPPClient(client.XMPPClient): |
33 | 20 |
34 def __init__(self, jid, password, host=None, port=5222, | 21 def __init__(self, jid, password, host=None, port=5222, |
35 check_certificate=True): | 22 tls_required=True, configurationForTLS=None): |
36 self.jid = jid | 23 self.jid = jid |
37 self.domain = jid.host.encode('idna') | 24 self.domain = jid.host.encode('idna') |
38 self.host = host | 25 self.host = host |
39 self.port = port | 26 self.port = port |
40 | 27 |
41 factory = HybridClientFactory( | 28 factory = HybridClientFactory( |
42 jid, password, check_certificate=check_certificate) | 29 jid, password, tls_required=tls_required, |
30 configurationForTLS=configurationForTLS) | |
43 | 31 |
44 client.StreamManager.__init__(self, factory) | 32 client.StreamManager.__init__(self, factory) |
45 | 33 |
46 | 34 |
47 def HybridClientFactory(jid, password, check_certificate=True): | 35 def HybridClientFactory(jid, password, tls_required=True, configurationForTLS=None): |
48 a = HybridAuthenticator(jid, password, check_certificate) | 36 a = HybridAuthenticator(jid, password, tls_required, configurationForTLS) |
49 | 37 |
50 return xmlstream.XmlStreamFactory(a) | 38 return xmlstream.XmlStreamFactory(a) |
51 | 39 |
52 | 40 |
53 class HybridAuthenticator(client.HybridAuthenticator): | 41 class HybridAuthenticator(client.HybridAuthenticator): |
54 res_binding = True | 42 res_binding = True |
55 | 43 |
56 def __init__(self, jid, password, check_certificate): | 44 def __init__(self, jid, password, tls_required=True, configurationForTLS=None): |
57 xmlstream.ConnectAuthenticator.__init__(self, jid.host) | 45 xmlstream.ConnectAuthenticator.__init__(self, jid.host) |
58 self.jid = jid | 46 self.jid = jid |
59 self.password = password | 47 self.password = password |
60 self.check_certificate = check_certificate | 48 self.tls_required = tls_required |
49 self.configurationForTLS = configurationForTLS | |
61 | 50 |
62 def associateWithStream(self, xs): | 51 def associateWithStream(self, xs): |
63 xmlstream.ConnectAuthenticator.associateWithStream(self, xs) | 52 xmlstream.ConnectAuthenticator.associateWithStream(self, xs) |
64 | 53 |
65 tlsInit = xmlstream.TLSInitiatingInitializer(xs) | 54 tlsInit = xmlstream.TLSInitiatingInitializer( |
66 tlsInit.check_certificate = self.check_certificate | 55 xs, required=self.tls_required, configurationForTLS=self.configurationForTLS) |
67 xs.initializers = [client.client.CheckVersionInitializer(xs), | 56 xs.initializers = [client.client.CheckVersionInitializer(xs), |
68 tlsInit, | 57 tlsInit, |
69 CheckAuthInitializer(xs, self.res_binding)] | 58 CheckAuthInitializer(xs, self.res_binding)] |
70 | 59 |
71 | 60 |
82 self._onElementHooks = [] | 71 self._onElementHooks = [] |
83 self._sendHooks = [] | 72 self._sendHooks = [] |
84 | 73 |
85 def addHook(self, hook_type, callback): | 74 def addHook(self, hook_type, callback): |
86 """Add a send or receive hook""" | 75 """Add a send or receive hook""" |
87 conflict_msg = ("Hook conflict: can't add {hook_type} hook {callback}" | 76 conflict_msg = f"Hook conflict: can't add {hook_type} hook {callback}" |
88 .format(hook_type=hook_type, callback=callback)) | |
89 if hook_type == C.STREAM_HOOK_RECEIVE: | 77 if hook_type == C.STREAM_HOOK_RECEIVE: |
90 if callback not in self._onElementHooks: | 78 if callback not in self._onElementHooks: |
91 self._onElementHooks.append(callback) | 79 self._onElementHooks.append(callback) |
92 else: | 80 else: |
93 log.warning(conflict_msg) | 81 log.warning(conflict_msg) |
95 if callback not in self._sendHooks: | 83 if callback not in self._sendHooks: |
96 self._sendHooks.append(callback) | 84 self._sendHooks.append(callback) |
97 else: | 85 else: |
98 log.warning(conflict_msg) | 86 log.warning(conflict_msg) |
99 else: | 87 else: |
100 raise ValueError("Invalid hook type: {hook_type}" | 88 raise ValueError(f"Invalid hook type: {hook_type}") |
101 .format(hook_type=hook_type)) | |
102 | 89 |
103 def onElement(self, element): | 90 def onElement(self, element): |
104 for hook in self._onElementHooks: | 91 for hook in self._onElementHooks: |
105 hook(element) | 92 hook(element) |
106 xmlstream.XmlStream.onElement(self, element) | 93 xmlstream.XmlStream.onElement(self, element) |
159 jid.__internJIDs[jidstring] = j | 146 jid.__internJIDs[jidstring] = j |
160 return copy.copy(j) | 147 return copy.copy(j) |
161 | 148 |
162 | 149 |
163 def apply(): | 150 def apply(): |
164 # FIXME: certificate validation is now implemented in Twisted trunk, to be removed | 151 # certificate validation |
165 # # certificate validation | 152 client.XMPPClient = XMPPClient |
166 # xmlstream.TLSInitiatingInitializer = TLSInitiatingInitializer | |
167 # client.XMPPClient = XMPPClient | |
168 # XmlStream triggers | 153 # XmlStream triggers |
169 xmlstream.XmlStreamFactory.protocol = XmlStream | 154 xmlstream.XmlStreamFactory.protocol = XmlStream |
170 # jid fix | 155 # jid fix |
171 jid.internJID = internJID | 156 jid.internJID = internJID |