source:
ralphm-patches/xmpp_client_listener.patch
@
37:03cd0cb8548c
Last change on this file since 37:03cd0cb8548c was 34:e46c5701df9e, checked in by Ralph Meijer <ralphm@…>, 13 years ago | |
---|---|
File size: 6.2 KB |
-
wokkel/client.py
diff -r c9d1bf0b783d wokkel/client.py
a b 10 10 that should probably eventually move there. 11 11 """ 12 12 13 import base64 14 13 15 from twisted.application import service 14 from twisted.internet import reactor16 from twisted.internet import defer, reactor 15 17 from twisted.names.srvconnect import SRVConnector 16 from twisted.words.protocols.jabber import client, sasl, xmlstream 18 from twisted.python import log 19 from twisted.words.protocols.jabber import client, error, sasl, xmlstream 20 from twisted.words.protocols.jabber.jid import internJID as JID 21 from twisted.words.xish import domish 17 22 18 23 from wokkel import generic 19 24 from wokkel.subprotocols import StreamManager 20 25 26 NS_CLIENT = 'jabber:client' 27 28 XPATH_ALL = "/*" 29 XPATH_AUTH = "/auth[@xmlns='%s']" % sasl.NS_XMPP_SASL 30 XPATH_BIND = "/iq[@type='set']/bind[@xmlns='%s']" % client.NS_XMPP_BIND 31 XPATH_SESSION = "/iq[@type='set']/session[@xmlns='%s']" % \ 32 client.NS_XMPP_SESSION 33 21 34 class CheckAuthInitializer(object): 22 35 """ 23 36 Check what authentication methods are available. … … 51 64 autentication. 52 65 """ 53 66 54 namespace = 'jabber:client'67 namespace = NS_CLIENT 55 68 56 69 def __init__(self, jid, password): 57 70 xmlstream.ConnectAuthenticator.__init__(self, jid.host) … … 186 199 c = XMPPClientConnector(reactor, domain, factory) 187 200 c.connect() 188 201 return factory.deferred 202 203 204 205 class XMPPClientListenAuthenticator(xmlstream.ListenAuthenticator): 206 namespace = NS_CLIENT 207 208 def __init__(self, domain): 209 self.domain = domain 210 self.failureGrace = 3 211 self.state = 'auth' 212 213 214 def associateWithStream(self, xs): 215 xmlstream.ListenAuthenticator.associateWithStream(self, xs) 216 self.xmlstream.addObserver(XPATH_ALL, self.onElementFallback, -1) 217 218 219 def onElementFallback(self, element): 220 if element.handled: 221 return 222 223 exc = error.StreamError('not-authorized') 224 self.xmlstream.sendStreamError(exc) 225 226 227 def streamStarted(self, rootElement): 228 xmlstream.ListenAuthenticator.streamStarted(self, rootElement) 229 230 # check namespace 231 #if self.xmlstream.namespace != self.namespace: 232 # self.xmlstream.namespace = self.namespace 233 # exc = error.StreamError('invalid-namespace') 234 # self.xmlstream.sendStreamError(exc) 235 # return 236 237 # TODO: check domain 238 239 self.xmlstream.sendHeader() 240 241 try: 242 stateHandlerName = 'streamStarted' + self.state.capitalize() 243 stateHandler = getattr(self, stateHandlerName) 244 except AttributeError: 245 log.msg('streamStarted handler for', self.state, 'not found') 246 else: 247 stateHandler() 248 249 250 def toState(self, state): 251 self.state = state 252 if state == 'initialized': 253 self.xmlstream.removeObserver(XPATH_ALL, self.onElementFallback) 254 self.xmlstream.addOnetimeObserver(XPATH_SESSION, self.onSession, 1) 255 self.xmlstream.dispatch(self.xmlstream, 256 xmlstream.STREAM_AUTHD_EVENT) 257 258 259 def streamStartedAuth(self): 260 features = domish.Element((xmlstream.NS_STREAMS, 'features')) 261 features.addElement((sasl.NS_XMPP_SASL, 'mechanisms')) 262 features.mechanisms.addElement('mechanism', content='PLAIN') 263 self.xmlstream.send(features) 264 self.xmlstream.addOnetimeObserver(XPATH_AUTH, self.onAuth) 265 266 267 def onAuth(self, auth): 268 auth.handled = True 269 270 if auth.getAttribute('mechanism') != 'PLAIN': 271 failure = domish.Element((sasl.NS_XMPP_SASL, 'failure')) 272 failure.addElement('invalid-mechanism') 273 self.xmlstream.send(failure) 274 275 # Close stream on too many failing authentication attempts 276 self.failureGrace -= 1 277 if self.failureGrace == 0: 278 self.xmlstream.sendFooter() 279 else: 280 self.xmlstream.addOnetimeObserver(XPATH_AUTH, self.onAuth) 281 282 return 283 284 initialResponse = base64.b64decode(unicode(auth)) 285 authzid, authcid, passwd = initialResponse.split('\x00') 286 287 # TODO: check passwd 288 289 # authenticated 290 291 self.username = authcid 292 293 success = domish.Element((sasl.NS_XMPP_SASL, 'success')) 294 self.xmlstream.send(success) 295 self.xmlstream.reset() 296 297 self.toState('bind') 298 299 300 def streamStartedBind(self): 301 features = domish.Element((xmlstream.NS_STREAMS, 'features')) 302 features.addElement((client.NS_XMPP_BIND, 'bind')) 303 features.addElement((client.NS_XMPP_SESSION, 'session')) 304 self.xmlstream.send(features) 305 self.xmlstream.addOnetimeObserver(XPATH_BIND, self.onBind) 306 307 308 def doBind(self, iq): 309 iq.handled = True 310 self.resource = unicode(iq.bind) or 'default' 311 312 # TODO: check for resource conflicts 313 314 newJID = JID(tuple=(self.username, self.domain, self.resource)) 315 316 reply = domish.Element((None, 'iq')) 317 reply['type'] = 'result' 318 if iq.getAttribute('id'): 319 reply['id'] = iq['id'] 320 reply.addElement((client.NS_XMPP_BIND, 'bind')) 321 reply.bind.addElement((client.NS_XMPP_BIND, 'jid'), 322 content=newJID.full()) 323 self.xmlstream.send(reply) 324 return defer.succeed(newJID) 325 326 327 def onBind(self, iq): 328 def cb(jid): 329 self.xmlstream.otherEntity = jid 330 self.toState('initialized') 331 332 def eb(failure): 333 if not isinstance(failure, error.StanzaError): 334 log.msg(failure) 335 exc = error.StanzaError('internal-server-error') 336 else: 337 exc = failure.value 338 self.xmlstream.send(exc.toResponse(iq)) 339 340 d = defer.maybeDeferred(self.doBind, iq) 341 d.addCallbacks(cb, eb) 342 343 344 def onSession(self, iq): 345 iq.handled = True 346 347 reply = domish.Element((None, 'iq')) 348 reply['type'] = 'result' 349 if iq.getAttribute('id'): 350 reply['id'] = iq['id'] 351 reply.addElement((client.NS_XMPP_SESSION, 'session')) 352 self.xmlstream.send(reply)
Note: See TracBrowser
for help on using the repository browser.