Exemple #1
0
    def onVerify(self, verify):
        try:
            receivingServer = jid.JID(verify['from']).host
            originatingServer = jid.JID(verify['to']).host
        except (KeyError, jid.InvalidFormat):
            raise error.StreamError('improper-addressing')

        if originatingServer not in self.service.domains:
            raise error.StreamError('host-unknown')

        if (self.xmlstream.otherEntity
                and receivingServer != self.xmlstream.otherEntity.host):
            raise error.StreamError('invalid-from')

        streamID = verify.getAttribute('id', '')
        key = unicode(verify)

        calculatedKey = generateKey(self.service.secret, receivingServer,
                                    originatingServer, streamID)
        validity = (key == calculatedKey) and 'valid' or 'invalid'

        reply = domish.Element((NS_DIALBACK, 'verify'))
        reply['from'] = originatingServer
        reply['to'] = receivingServer
        reply['id'] = streamID
        reply['type'] = validity
        self.xmlstream.send(reply)
Exemple #2
0
    def streamStarted(self, rootElement):
        """
        Called by the stream when it has started.

        This examines the default namespace of the incoming stream and whether
        there is a requested hostname for the component. Then it generates a
        stream identifier, sends a response header and adds an observer for
        the first incoming element, triggering L{onElement}.
        """

        xmlstream.ListenAuthenticator.streamStarted(self, rootElement)

        # Compatibility fix for pre-8.2 implementations of ListenAuthenticator
        if not self.xmlstream.sid:
            from twisted.python import randbytes
            self.xmlstream.sid = randbytes.secureRandom(8).encode('hex')

        if rootElement.defaultUri != self.namespace:
            exc = error.StreamError('invalid-namespace')
            self.xmlstream.sendStreamError(exc)
            return

        # self.xmlstream.thisEntity is set to the address the component
        # wants to assume.
        if not self.xmlstream.thisEntity:
            exc = error.StreamError('improper-addressing')
            self.xmlstream.sendStreamError(exc)
            return

        self.xmlstream.sendHeader()
        self.xmlstream.addOnetimeObserver('/*', self.onElement)
    def streamStarted(self, rootElement):
        """
        Called by the stream when it has started.

        This examines the default namespace of the incoming stream and whether
        there is a requested hostname for the component. Then it generates a
        stream identifier, sends a response header and adds an observer for
        the first incoming element, triggering L{onElement}.
        """

        xmlstream.ListenAuthenticator.streamStarted(self, rootElement)

        if rootElement.defaultUri != self.namespace:
            exc = error.StreamError("invalid-namespace")
            self.xmlstream.sendStreamError(exc)
            return

        # self.xmlstream.thisEntity is set to the address the component
        # wants to assume.
        if not self.xmlstream.thisEntity:
            exc = error.StreamError("improper-addressing")
            self.xmlstream.sendStreamError(exc)
            return

        self.xmlstream.sendHeader()
        self.xmlstream.addOnetimeObserver("/*", self.onElement)
Exemple #4
0
    def dispatch(self, xs, stanza):
        """
        Send a stanza to the router, checking some stuff first.
        """

        log.debug("stanza from %s: %s" %
                  (xs.otherEntity.full(), stanza.toXml()))
        util.resetNamespace(stanza, xs.namespace)
        stanzaFrom = stanza.getAttribute('from')
        stanzaTo = stanza.getAttribute('to')

        if not stanza.bind and not stanzaFrom or not stanzaTo:
            xs.sendStreamError(error.StreamError('improper-addressing'))
        else:
            try:
                sender = jid.internJID(stanzaFrom)
                jid.internJID(stanzaTo)
            except jid.InvalidFormat:
                log.debug("dropping stanza with malformed JID")

            log.debug("sender = %s, otherEntity = %s" %
                      (sender.full(), xs.otherEntity.full()))

            try:
                unused, host = util.jid_component(sender.host)
                if host in self.keyring.hostlist():
                    self.router.send(stanza)
                else:
                    raise Exception()
            except:
                xs.sendStreamError(error.StreamError('invalid-from'))
Exemple #5
0
    def streamStarted(self, rootElement):
        xmlstream.ListenAuthenticator.streamStarted(self, rootElement)

        # Compatibility fix for pre-8.2 implementations of ListenAuthenticator
        if not self.xmlstream.sid:
            self.xmlstream.sid = randbytes.secureRandom(8).encode('hex')

        if self.xmlstream.thisEntity:
            targetDomain = self.xmlstream.thisEntity.host
        else:
            targetDomain = self.service.defaultDomain

        def prepareStream(domain):
            self.xmlstream.namespace = self.namespace
            self.xmlstream.prefixes = {
                xmlstream.NS_STREAMS: 'stream',
                NS_DIALBACK: 'db'
            }
            if domain:
                self.xmlstream.thisEntity = jid.internJID(domain)

        try:
            if xmlstream.NS_STREAMS != rootElement.uri or \
               self.namespace != self.xmlstream.namespace or \
               ('db', NS_DIALBACK) not in rootElement.localPrefixes.iteritems():
                raise error.StreamError('invalid-namespace')

            if targetDomain and targetDomain not in self.service.domains:
                raise error.StreamError('host-unknown')
        except error.StreamError, exc:
            prepareStream(self.service.defaultDomain)
            self.xmlstream.sendStreamError(exc)
            return
Exemple #6
0
    def streamStarted(self, rootElement):
        xmlstream.ListenAuthenticator.streamStarted(self, rootElement)

        self.xmlstream.sendHeader()

        try:
            if self.xmlstream.version < (1, 0):
                raise error.StreamError('unsupported-version')
            if self.xmlstream.thisEntity.host != self.network:
                raise error.StreamError('not-authorized')
        except error.StreamError, exc:
            self.xmlstream.sendHeader()
            self.xmlstream.sendStreamError(exc)
            return
 def test_getElementPlain(self):
     """
     Test namespace of the element representation of an error.
     """
     e = error.StreamError('feature-not-implemented')
     element = e.getElement()
     self.assertEqual(element.uri, NS_STREAMS)
Exemple #8
0
 def validateConnection(self, xs):
     otherHost = xs.otherEntity.host
     if otherHost in self._outgoingStreams:
         xs.sendStreamError(error.StreamError('conflict'))
         return False
     self._outgoingStreams[otherHost] = xs
     return True
 def test_getElementTextNamespace(self):
     """
     Test that the error text element has the correct namespace.
     """
     e = error.StreamError('feature-not-implemented', 'text')
     element = e.getElement()
     self.assertEqual(NS_XMPP_STREAMS, element.text.uri)
Exemple #10
0
 def onVerify(self, verify):
     self.xmlstream.removeObserver(xmlstream.STREAM_ERROR_EVENT,
                                   self.onStreamError)
     if verify['id'] != self.originalStreamID:
         self.xmlstream.sendStreamError(error.StreamError('invalid-id'))
         self._deferred.errback(DialbackFailed())
     elif verify['to'] != self.thisHost:
         self.xmlstream.sendStreamError(error.StreamError('host-unknown'))
         self._deferred.errback(DialbackFailed())
     elif verify['from'] != self.otherHost:
         self.xmlstream.sendStreamError(error.StreamError('invalid-from'))
         self._deferred.errback(DialbackFailed())
     elif verify['type'] == 'valid':
         self._deferred.callback(None)
     else:
         self._deferred.errback(DialbackFailed())
Exemple #11
0
 def _unauthorized(self, stanza):
     if not stanza.consumed and (not stanza.hasAttribute('to')
                                 or stanza['to'] != self.network):
         stanza.consumed = True
         self.xmlstream.sendStreamError(error.StreamError('not-authorized'))
         # refuse to process any more stanzas
         self.xmlstream.setDispatchFn(None)
Exemple #12
0
 def test_getElementConditionNamespace(self):
     """
     Test that the error condition element has the correct namespace.
     """
     e = error.StreamError('feature-not-implemented')
     element = e.getElement()
     self.assertEquals(NS_XMPP_STREAMS, getattr(element, 'feature-not-implemented').uri)
Exemple #13
0
 def wrappedObserver(element):
     try:
         observer(element)
     except error.StreamError as exc:
         xs.sendStreamError(exc)
     except:
         log.err()
         exc = error.StreamError('internal-server-error')
         xs.sendStreamError(exc)
Exemple #14
0
 def _timeout(self):
     self.ping_timeout = None
     # send stream error
     self.xmlstream.sendStreamError(error.StreamError('connection-timeout'))
     # broadcast unavailable presence
     if self.xmlstream.otherEntity is not None:
         stanza = xmppim.UnavailablePresence()
         stanza['from'] = self.xmlstream.otherEntity.full()
         self.parent.forward(stanza)
Exemple #15
0
    def dispatch(self, xs, stanza):
        """
        Send on element to be routed within the server.
        """
        stanzaFrom = stanza.getAttribute('from')
        stanzaTo = stanza.getAttribute('to')

        if not stanzaFrom or not stanzaTo:
            xs.sendStreamError(error.StreamError('improper-addressing'))
        else:
            try:
                sender = jid.internJID(stanzaFrom)
                jid.internJID(stanzaTo)
            except jid.InvalidFormat:
                log.msg("Dropping error stanza with malformed JID")

            if sender.host != xs.otherEntity.host:
                xs.sendStreamError(error.StreamError('invalid-from'))
            else:
                self.xmlstream.send(stanza)
Exemple #16
0
    def streamStarted(self, rootElement):
        xmlstream.ListenAuthenticator.streamStarted(self, rootElement)

        if self.xmlstream.thisEntity:
            targetDomain = self.xmlstream.thisEntity.host
        else:
            targetDomain = self.service.defaultDomain

        def prepareStream(domain):
            self.xmlstream.namespace = self.namespace
            self.xmlstream.prefixes = {xmlstream.NS_STREAMS: 'stream',
                                       NS_DIALBACK: 'db'}
            if domain:
                self.xmlstream.thisEntity = jid.internJID(domain)

        try:
            if xmlstream.NS_STREAMS != rootElement.uri or \
               self.namespace != self.xmlstream.namespace or \
               ('db', NS_DIALBACK) not in iteritems(rootElement.localPrefixes):
                raise error.StreamError('invalid-namespace')

            if targetDomain and targetDomain not in self.service.domains:
                raise error.StreamError('host-unknown')
        except error.StreamError as exc:
            prepareStream(self.service.defaultDomain)
            self.xmlstream.sendStreamError(exc)
            return

        self.xmlstream.addObserver("//verify[@xmlns='%s']" % NS_DIALBACK,
                                   trapStreamError(self.xmlstream,
                                                   self.onVerify))
        self.xmlstream.addObserver("//result[@xmlns='%s']" % NS_DIALBACK,
                                   self.onResult)

        prepareStream(targetDomain)
        self.xmlstream.sendHeader()

        if self.xmlstream.version >= (1, 0):
            features = domish.Element((xmlstream.NS_STREAMS, 'features'))
            self.xmlstream.send(features)
    def test_sendStreamErrorReceiving(self):
        """
        Test sendStreamError on a receiving xmlstream with a header sent.

        An error should be sent out and the connection lost.
        """
        xs = self.xmlstream
        xs.initiating = False
        xs.sendHeader()
        xs.transport.clear()
        xs.sendStreamError(error.StreamError('version-unsupported'))
        self.assertNotEqual(b'', xs.transport.value())
        self.assertTrue(self.gotStreamEnd)
    def onElement(self, element):
        """
        Called on incoming XML Stanzas.

        The very first element received should be a request for handshake.
        Otherwise, the stream is dropped with a 'not-authorized' error. If a
        handshake request was received, the hash is extracted and passed to
        L{onHandshake}.
        """
        if (element.uri, element.name) == (self.namespace, "handshake"):
            self.onHandshake(str(element))
        else:
            exc = error.StreamError("not-authorized")
            self.xmlstream.sendStreamError(exc)
    def test_sendStreamErrorReceivingNoHeader(self):
        """
        Test sendStreamError on a receiving xmlstream without having sent a
        header.

        In this case, a header should be generated. Then, the error should
        be sent out on the stream followed by closing the connection.
        """
        xs = self.xmlstream
        xs.initiating = False
        xs.transport.clear()
        xs.sendStreamError(error.StreamError('version-unsupported'))
        self.assertTrue(xs._headerSent)
        self.assertNotEqual(b'', xs.transport.value())
        self.assertTrue(self.gotStreamEnd)
Exemple #20
0
    def dispatch(self, xs, stanza):
        """
        Send a stanza to the router, checking some stuff first.
        """

        util.resetNamespace(stanza, xs.namespace)
        stanzaFrom = stanza.getAttribute('from')
        stanzaTo = stanza.getAttribute('to')

        if not stanzaFrom or not stanzaTo:
            xs.sendStreamError(error.StreamError('improper-addressing'))
        else:
            try:
                sender = jid.internJID(stanzaFrom)
                jid.internJID(stanzaTo)
            except jid.InvalidFormat:
                log.debug("Dropping error stanza with malformed JID")

            log.debug("sender = %s, otherEntity = %s" %
                      (sender.full(), xs.otherEntity.full()))
            if sender.host != xs.otherEntity.host and sender.host != self.defaultDomain:
                xs.sendStreamError(error.StreamError('invalid-from'))
            else:
                self.router.send(stanza)
    def test_sendStreamErrorInitiatingNoHeader(self):
        """
        Test sendStreamError on an initiating xmlstream without having sent a
        header.

        In this case, no header should be generated. Also, the error should
        not be sent out on the stream. Just closing the connection.
        """
        xs = self.xmlstream
        xs.initiating = True
        xs.transport.clear()
        xs.sendStreamError(error.StreamError('version-unsupported'))
        self.assertNot(xs._headerSent)
        self.assertEqual(b'', xs.transport.value())
        self.assertTrue(self.gotStreamEnd)
Exemple #22
0
    def onHandshake(self, handshake):
        """
        Called upon receiving the handshake request.

        This checks that the given hash in C{handshake} is equal to a
        calculated hash, responding with a handshake reply or a stream error.
        If the handshake was ok, the stream is authorized, and  XML Stanzas may
        be exchanged.
        """
        calculatedHash = xmlstream.hashPassword(self.xmlstream.sid, str(self.secret))
        if handshake != calculatedHash:
            exc = error.StreamError("not-authorized", text="Invalid hash")
            self.xmlstream.sendStreamError(exc)
        else:
            self.xmlstream.send("<handshake/>")
            self.xmlstream.dispatch(self.xmlstream, xmlstream.STREAM_AUTHD_EVENT)
Exemple #23
0
    def streamStarted(self, rootElement):
        # TODO same checking code on listening authenticator

        # check that from attribute is associated to the right key
        host = rootElement['from']
        fingerprint = self.xmlstream.transport.getPeerCertificate().fingerprint
        log.debug("%s fingerprint is %s" % (
            host,
            fingerprint,
        ))

        valid = False
        # FIXME accessing Keyring internals
        for fpr, fhost in self.keyring._list.iteritems():
            if fhost == host and fpr.upper() == fingerprint:
                log.debug("fingerprint matching (%s = %s)" % (host, fpr))
                valid = True

        if valid:
            xmlstream.ConnectAuthenticator.streamStarted(self, rootElement)
        else:
            self.xmlstream.sendStreamError(error.StreamError('not-authorized'))
Exemple #24
0
    def onElementFallback(self, element):
        if element.handled:
            return

        exc = error.StreamError('not-authorized')
        self.xmlstream.sendStreamError(exc)
Exemple #25
0
 def conflict(self):
     if self.xmlstream:
         self.xmlstream.sendStreamError(error.StreamError('conflict'))
         # refuse to process any more stanzas
         self.xmlstream.setDispatchFn(None)
Exemple #26
0
 def testGetElementPlain(self):
     e = error.StreamError('feature-not-implemented')
     element = e.getElement()
     self.assertEquals(element.uri, NS_STREAMS)
Exemple #27
0
 def conflict(self):
     if self.xmlstream:
         self.xmlstream.sendStreamError(error.StreamError('conflict'))
Exemple #28
0
 def initialize(self):
     if self.xmlstream.version < (1, 0):
         raise error.StreamError('unsupported-version')
Exemple #29
0
 def _unauthorized(self, stanza):
     if not stanza.consumed and (not stanza.hasAttribute('to')
                                 or stanza['to'] != self.network):
         stanza.consumed = True
         self.xmlstream.sendStreamError(error.StreamError('not-authorized'))
Exemple #30
0
    This wraps an observer to catch exceptions. In case of a
    L{error.StreamError}, it is send over the given XML stream. All other
    exceptions yield a C{'internal-server-error'} stream error, that is
    sent over the stream, while the exception is logged.

    @return: Wrapped observer
    """
    def wrappedObserver(element):
        try:
            observer(element)
        except error.StreamError, exc:
            xs.sendStreamError(exc)
        except:
            log.err()
            exc = error.StreamError('internal-server-error')
            xs.sendStreamError(exc)

    return wrappedObserver


class XMPPServerConnector(SRVConnector):
    def __init__(self, reactor, domain, factory):
        SRVConnector.__init__(self, reactor, 'xmpp-server', domain, factory)

    def pickServer(self):
        host, port = SRVConnector.pickServer(self)

        if not self.servers and not self.orderedServers:
            # no SRV record, fall back..
            port = 5269