Mercurial > libervia-backend
comparison sat/plugins/plugin_xep_0077.py @ 2838:8018cf9aa55b
plugin XEP-0077: correctly report invalid certificate + errback on unexpected stream close
author | Goffi <goffi@goffi.org> |
---|---|
date | Sun, 03 Mar 2019 19:18:45 +0100 |
parents | 003b8b4b56a7 |
children | ab2696e34d29 |
comparison
equal
deleted
inserted
replaced
2837:e2005dd39c92 | 2838:8018cf9aa55b |
---|---|
21 from sat.core.constants import Const as C | 21 from sat.core.constants import Const as C |
22 from sat.core import exceptions | 22 from sat.core import exceptions |
23 from sat.core.log import getLogger | 23 from sat.core.log import getLogger |
24 | 24 |
25 log = getLogger(__name__) | 25 log = getLogger(__name__) |
26 from twisted.words.protocols.jabber import jid, xmlstream, client | 26 from twisted.words.protocols.jabber import jid, xmlstream, client, error as jabber_error |
27 from twisted.internet import defer, reactor | 27 from twisted.internet import defer, reactor |
28 from sat.tools import xml_tools | 28 from sat.tools import xml_tools |
29 | 29 |
30 from wokkel import data_form | 30 from wokkel import data_form |
31 | 31 |
48 # FIXME: request IQ is not send to check available fields, | 48 # FIXME: request IQ is not send to check available fields, |
49 # while XEP recommand to use it | 49 # while XEP recommand to use it |
50 # FIXME: doesn't handle data form or oob | 50 # FIXME: doesn't handle data form or oob |
51 namespace = 'jabber:client' | 51 namespace = 'jabber:client' |
52 | 52 |
53 def __init__(self, jid_, password, email=None): | 53 def __init__(self, jid_, password, email=None, check_certificate=True): |
54 log.debug(_(u"Registration asked for {jid}").format(jid=jid_)) | 54 log.debug(_(u"Registration asked for {jid}").format(jid=jid_)) |
55 xmlstream.ConnectAuthenticator.__init__(self, jid_.host) | 55 xmlstream.ConnectAuthenticator.__init__(self, jid_.host) |
56 self.jid = jid_ | 56 self.jid = jid_ |
57 self.password = password | 57 self.password = password |
58 self.email = email | 58 self.email = email |
59 self.check_certificate = check_certificate | |
59 self.registered = defer.Deferred() | 60 self.registered = defer.Deferred() |
60 | 61 |
61 def associateWithStream(self, xs): | 62 def associateWithStream(self, xs): |
62 xmlstream.ConnectAuthenticator.associateWithStream(self, xs) | 63 xmlstream.ConnectAuthenticator.associateWithStream(self, xs) |
63 xs.addObserver(xmlstream.STREAM_AUTHD_EVENT, self.register) | 64 xs.addObserver(xmlstream.STREAM_AUTHD_EVENT, self.register) |
64 | 65 |
65 xs.initializers = [client.CheckVersionInitializer(xs)] | 66 xs.initializers = [client.CheckVersionInitializer(xs)] |
66 inits = [ (xmlstream.TLSInitiatingInitializer, False), | 67 tls_init = xmlstream.TLSInitiatingInitializer(xs) |
67 ] | 68 tls_init.required = False |
68 | 69 tls_init.check_certificate = self.check_certificate |
69 for initClass, required in inits: | 70 xs.initializers.append(tls_init) |
70 init = initClass(xs) | |
71 init.required = required | |
72 xs.initializers.append(init) | |
73 | 71 |
74 def register(self, xmlstream): | 72 def register(self, xmlstream): |
75 log.debug(_(u"Stream started with {server}, now registering" | 73 log.debug(_(u"Stream started with {server}, now registering" |
76 .format(server=self.jid.host))) | 74 .format(server=self.jid.host))) |
77 iq = XEP_0077.buildRegisterIQ(self.xmlstream, self.jid, self.password, self.email) | 75 iq = XEP_0077.buildRegisterIQ(self.xmlstream, self.jid, self.password, self.email) |
84 | 82 |
85 def registrationEb(self, failure_): | 83 def registrationEb(self, failure_): |
86 log.info(_("Registration failure: {}").format(unicode(failure_.value))) | 84 log.info(_("Registration failure: {}").format(unicode(failure_.value))) |
87 self.xmlstream.sendFooter() | 85 self.xmlstream.sendFooter() |
88 raise failure_ | 86 raise failure_ |
87 | |
88 | |
89 class ServerRegister(xmlstream.XmlStreamFactory): | |
90 | |
91 def __init__(self, *args, **kwargs): | |
92 xmlstream.XmlStreamFactory.__init__(self, *args, **kwargs) | |
93 self.addBootstrap(xmlstream.STREAM_END_EVENT, self._disconnected) | |
94 | |
95 def clientConnectionLost(self, connector, reason): | |
96 connector.disconnect() | |
97 | |
98 def _disconnected(self, reason): | |
99 if not self.authenticator.registered.called: | |
100 err = jabber_error.StreamError(u"Server unexpectedly closed the connection") | |
101 try: | |
102 if reason.value.args[0][0][2] == "certificate verify failed": | |
103 err = exceptions.InvalidCertificate() | |
104 except (IndexError, TypeError): | |
105 pass | |
106 self.authenticator.registered.errback(err) | |
89 | 107 |
90 | 108 |
91 class XEP_0077(object): | 109 class XEP_0077(object): |
92 def __init__(self, host): | 110 def __init__(self, host): |
93 log.info(_("Plugin XEP_0077 initialization")) | 111 log.info(_("Plugin XEP_0077 initialization")) |
235 @param password(unicode): password of the account | 253 @param password(unicode): password of the account |
236 @param email(unicode): email of the account | 254 @param email(unicode): email of the account |
237 @param host(unicode): host of the server to register to | 255 @param host(unicode): host of the server to register to |
238 @param port(int): port of the server to register to | 256 @param port(int): port of the server to register to |
239 """ | 257 """ |
240 authenticator = RegisteringAuthenticator(jid_, password, email) | 258 check_certificate = host != u"127.0.0.1" |
259 authenticator = RegisteringAuthenticator( | |
260 jid_, password, email, check_certificate=check_certificate) | |
241 registered_d = authenticator.registered | 261 registered_d = authenticator.registered |
242 serverRegistrer = xmlstream.XmlStreamFactory(authenticator) | 262 server_register = ServerRegister(authenticator) |
243 connector = reactor.connectTCP(host, port, serverRegistrer) | 263 reactor.connectTCP(host, port, server_register) |
244 serverRegistrer.clientConnectionLost = lambda conn, reason: connector.disconnect() | |
245 return registered_d | 264 return registered_d |
246 | 265 |
247 def _changePassword(self, new_password, profile_key): | 266 def _changePassword(self, new_password, profile_key): |
248 client = self.host.getClient(profile_key) | 267 client = self.host.getClient(profile_key) |
249 return self.changePassword(client, new_password) | 268 return self.changePassword(client, new_password) |