Ejemplo n.º 1
0
    def test_fail_on_protocol_violation(self):
        user = "******"
        password = "******"

        smmock = aiosasl.SASLStateMachine(SASLInterfaceMock(
            self,
            [
                ("auth;PLAIN",
                 b"\0tim\0tanstaaftanstaaf",
                 "challenge",
                 b"foo")
            ]))

        @asyncio.coroutine
        def provide_credentials(*args):
            return user, password

        def run():
            plain = aiosasl.PLAIN(provide_credentials)
            yield from plain.authenticate(
                smmock,
                "PLAIN")

        with self.assertRaisesRegexp(aiosasl.SASLFailure,
                                     "protocol violation") as ctx:
            asyncio.get_event_loop().run_until_complete(run())

        self.assertEqual(
            None,
            ctx.exception.opaque_error
        )

        smmock.interface.finalize()
Ejemplo n.º 2
0
    def test_passes_token_through_trace(self):
        with unittest.mock.patch("aiosasl.trace") as trace:
            trace.return_value = "traced"

            anon = aiosasl.ANONYMOUS(unittest.mock.sentinel.token)

        trace.assert_called_with(unittest.mock.sentinel.token)

        smmock = aiosasl.SASLStateMachine(SASLInterfaceMock(
            self,
            [
                ("auth;ANONYMOUS",
                 b"traced",
                 "success",
                 None)
            ]))

        def run():
            result = yield from anon.authenticate(
                smmock,
                "ANONYMOUS")
            self.assertTrue(result)

        asyncio.get_event_loop().run_until_complete(run())

        smmock.interface.finalize()
Ejemplo n.º 3
0
    def test_rfc(self):
        user = "******"
        password = "******"

        smmock = aiosasl.SASLStateMachine(SASLInterfaceMock(
            self,
            [
                ("auth;PLAIN",
                 b"\0tim\0tanstaaftanstaaf",
                 "success",
                 None)
            ]))

        @asyncio.coroutine
        def provide_credentials(*args):
            return user, password

        def run():
            plain = aiosasl.PLAIN(provide_credentials)
            result = yield from plain.authenticate(
                smmock,
                "PLAIN")
            self.assertTrue(result)

        asyncio.get_event_loop().run_until_complete(run())

        smmock.interface.finalize()
Ejemplo n.º 4
0
    def test_malformed_reply(self):
        smmock = aiosasl.SASLStateMachine(SASLInterfaceMock(
            self,
            [
                ("auth;SCRAM-SHA-1-PLUS",
                 b"p=tls-unique,,"+self.client_first_message_bare,
                 "challenge",
                 b"s=hut,t=hefu,c=kup,d=onny"),
                ("abort", None,
                 "failure", ("aborted", None))
            ]))

        with self.assertRaises(aiosasl.SASLFailure) as ctx:
            self._run(
                smmock,
                aiosasl.SCRAMPLUS(
                    self._provide_credentials,
                    TLSUnique(self._tls_connection)
                )
            )

        self.assertIn(
            "malformed",
            str(ctx.exception).lower()
        )
Ejemplo n.º 5
0
    def test_reject_protocol_violation(self):
        smmock = aiosasl.SASLStateMachine(SASLInterfaceMock(
            self,
            [
                ("auth;SCRAM-SHA-1-PLUS",
                 b"p=tls-unique,,"+self.client_first_message_bare,
                 "challenge",
                 self.server_first_message),
                ("response",
                 self.client_final_message_without_proof +
                     b",p="+base64.b64encode(self.client_proof),
                 "challenge",
                 b"foo"),
                ("response", b"", "success", b"bar")
            ]))

        with self.assertRaisesRegexp(aiosasl.SASLFailure,
                                     "protocol violation") as ctx:
            self._run(
                smmock,
                aiosasl.SCRAMPLUS(
                    self._provide_credentials,
                    TLSUnique(self._tls_connection)
                )
            )

        self.assertEqual(
            None,
            ctx.exception.opaque_error
        )
Ejemplo n.º 6
0
    def test_promote_failure_to_authentication_failure(self):
        smmock = aiosasl.SASLStateMachine(SASLInterfaceMock(
            self,
            [
                ("auth;SCRAM-SHA-1-PLUS",
                 b"p=tls-unique,,"+self.client_first_message_bare,
                 "challenge",
                 self.server_first_message),
                ("response",
                 self.client_final_message_without_proof +
                     b",p="+base64.b64encode(self.client_proof),
                 "failure",
                 ("credentials-expired", None))
            ]))

        with self.assertRaises(aiosasl.AuthenticationFailure) as ctx:
            self._run(
                smmock,
                aiosasl.SCRAMPLUS(
                    self._provide_credentials,
                    TLSUnique(self._tls_connection)
                )
            )

        self.assertEqual(
            "credentials-expired",
            ctx.exception.opaque_error
        )
Ejemplo n.º 7
0
    def test_invalid_signature(self):
        smmock = aiosasl.SASLStateMachine(SASLInterfaceMock(
            self,
            [
                ("auth;SCRAM-SHA-1-PLUS",
                 b"p=tls-unique,,"+self.client_first_message_bare,
                 "challenge",
                 self.server_first_message),
                ("response",
                 self.client_final_message_without_proof +
                     b",p="+base64.b64encode(self.client_proof),
                 "success",
                 b"v="+base64.b64encode(b"fnord"))
            ]))

        with self.assertRaises(aiosasl.SASLFailure) as ctx:
            self._run(
                smmock,
                aiosasl.SCRAMPLUS(
                    self._provide_credentials,
                    TLSUnique(self._tls_connection)
                )
            )

        self.assertIsNone(ctx.exception.opaque_error)
        self.assertIn(
            "signature",
            str(ctx.exception).lower()
        )
Ejemplo n.º 8
0
    def test_other_malformed_reply(self):
        smmock = aiosasl.SASLStateMachine(SASLInterfaceMock(
            self,
            [
                ("auth;SCRAM-SHA-1-PLUS",
                 b"p=tls-unique,,"+self.client_first_message_bare,
                 "challenge",
                 b"i=sometext,s=ABC,r=Zm9vAAAAAAAAAAAAAAAA3rfcNHYJY1ZVvWVs7j"),
                ("abort", None,
                 "failure", ("aborted", None))
            ]))

        with self.assertRaises(aiosasl.SASLFailure) as ctx:
            self._run(
                smmock,
                aiosasl.SCRAMPLUS(
                    self._provide_credentials,
                    TLSUnique(self._tls_connection)
                )
            )

        self.assertIn(
            "malformed",
            str(ctx.exception).lower()
        )
Ejemplo n.º 9
0
    def _execute(self, intf, mechanism, token):
        """
        Execute a SASL authentication process.

        :param intf: SASL interface to use
        :type intf: :class:`~.sasl.SASLXMPPInterface`
        :param mechanism: SASL mechanism to use
        :type mechanism: :class:`aiosasl.SASLMechanism`
        :param token: The opaque token argument for the mechanism
        :type token: not :data:`None`
        :raises aiosasl.AuthenticationFailure: if authentication failed due to
                                               bad credentials
        :raises aiosasl.SASLFailure: on other SASL error conditions (such as
                                     protocol violations)
        :return: true if authentication succeeded, false if the mechanism has
                 to be disabled
        :rtype: :class:`bool`

        This executes the SASL authentication process. The more specific
        exceptions are generated by inspecting the
        :attr:`aiosasl.SASLFailure.opaque_error` on exceptinos raised from the
        :class:`~.sasl.SASLXMPPInterface`. Other :class:`aiosasl.SASLFailure`
        exceptions are re-raised without modification.
        """
        sm = aiosasl.SASLStateMachine(intf)
        try:
            yield from mechanism.authenticate(sm, token)
            return True
        except aiosasl.SASLFailure as err:
            if err.opaque_error in self.AUTHENTICATION_FAILURES:
                raise aiosasl.AuthenticationFailure(
                    opaque_error=err.opaque_error, text=err.text)
            elif err.opaque_error in self.MECHANISM_REJECTED_FAILURES:
                return False
            raise
Ejemplo n.º 10
0
    def setUp(self):
        self.loop = asyncio.get_event_loop()
        self.intf = unittest.mock.Mock()
        self.intf.initiate = CoroutineMock()
        self.intf.respond = CoroutineMock()
        self.intf.abort = CoroutineMock()
        self.sm = aiosasl.SASLStateMachine(self.intf)

        self.intf.initiate.return_value = (aiosasl.SASLState.SUCCESS, None)
Ejemplo n.º 11
0
    def test_reject_NUL_bytes_in_password(self):
        smmock = aiosasl.SASLStateMachine(SASLInterfaceMock(
            self,
            [
            ]))

        @asyncio.coroutine
        def provide_credentials(*args):
            return "foo", "\0"

        with self.assertRaises(ValueError):
            run_coroutine(
                aiosasl.PLAIN(provide_credentials).authenticate(smmock, "PLAIN")
            )
Ejemplo n.º 12
0
    def test_incorrect_nonce(self):
        smmock = aiosasl.SASLStateMachine(SASLInterfaceMock(
            self,
            [
                ("auth;SCRAM-SHA-1",
                 b"n,,"+self.client_first_message_bare,
                 "challenge",
                 b"r=foobar,s="+base64.b64encode(self.salt)+b",i=4096"),
                ("abort", None,
                 "failure", ("aborted", None))
            ]))

        with self.assertRaisesRegexp(aiosasl.SASLFailure, "nonce") as ctx:
            self._run(smmock, aiosasl.SCRAM(self._provide_credentials))

        self.assertIsNone(ctx.exception.opaque_error)
Ejemplo n.º 13
0
 def _execute(self, intf, mechanism, token):
     """
     Execute SASL negotiation using the given `mechanism` instance and
     `token` using the :class:`~.sasl.SASLXMPPInterface` `intf`.
     """
     sm = aiosasl.SASLStateMachine(intf)
     try:
         yield from mechanism.authenticate(sm, token)
         return True
     except aiosasl.SASLFailure as err:
         if err.opaque_error in self.AUTHENTICATION_FAILURES:
             raise aiosasl.AuthenticationFailure(
                 opaque_error=err.opaque_error, text=err.text)
         elif err.opaque_error in self.MECHANISM_REJECTED_FAILURES:
             return False
         raise
Ejemplo n.º 14
0
    def test_rfc_with_downgrade_protection(self):
        smmock = aiosasl.SASLStateMachine(SASLInterfaceMock(
            self,
            [
                ("auth;SCRAM-SHA-1",
                 b"y,,"+self.client_first_message_bare,
                 "challenge",
                 self.server_first_message),
                ("response",
                 self.client_final_message_without_proof +
                     b",p="+base64.b64encode(self.client_proof),
                 "success",
                 b"v="+base64.b64encode(self.server_signature))
            ]))

        self.assertTrue(self._run(
            smmock,
            aiosasl.SCRAM(self._provide_credentials, after_scram_plus=True)
        ))
Ejemplo n.º 15
0
    def test_high_iteration_count(self):
        smmock = aiosasl.SASLStateMachine(SASLInterfaceMock(
            self,
            [
                ("auth;SCRAM-SHA-1",
                 b"n,,"+self.client_first_message_bare,
                 "challenge",
                 self.server_first_message_5000),
                ("response",
                 self.client_final_message_without_proof +
                     b",p="+base64.b64encode(self.client_proof_5000),
                 "success",
                 b"v="+base64.b64encode(self.server_signature_5000))
            ]))

        self.assertTrue(self._run(
            smmock,
            aiosasl.SCRAM(self._provide_credentials)
        ))
Ejemplo n.º 16
0
    def test_reject_protocol_violation_2(self):
        smmock = aiosasl.SASLStateMachine(SASLInterfaceMock(
            self,
            [
                ("auth;SCRAM-SHA-1",
                 b"n,,"+self.client_first_message_bare,
                 "success", None),
                ("abort", None,
                 "failure", ("aborted", None)),
            ]))

        with self.assertRaisesRegexp(aiosasl.SASLFailure,
                                     "protocol violation") as ctx:
            self._run(smmock, aiosasl.SCRAM(self._provide_credentials))

        self.assertEqual(
            None,
            ctx.exception.opaque_error
        )
Ejemplo n.º 17
0
    def test_simply_sends_token(self):
        smmock = aiosasl.SASLStateMachine(SASLInterfaceMock(
            self,
            [
                ("auth;ANONYMOUS",
                 b"sirhc",
                 "success",
                 None)
            ]))

        def run():
            anon = aiosasl.ANONYMOUS("sirhc")
            result = yield from anon.authenticate(
                smmock,
                "ANONYMOUS")
            self.assertTrue(result)

        asyncio.get_event_loop().run_until_complete(run())

        smmock.interface.finalize()
Ejemplo n.º 18
0
    def test_rfc(self):
        smmock = aiosasl.SASLStateMachine(SASLInterfaceMock(
            self,
            [
                ("auth;SCRAM-SHA-1-PLUS",
                 b"p=tls-unique,,"+self.client_first_message_bare,
                 "challenge",
                 self.server_first_message),
                ("response",
                 self.client_final_message_without_proof +
                     b",p="+base64.b64encode(self.client_proof),
                 "success",
                 b"v="+base64.b64encode(self.server_signature))
            ]))

        self.assertTrue(self._run(
            smmock,
            aiosasl.SCRAMPLUS(
                self._provide_credentials,
                TLSUnique(self._tls_connection)
            )
        ))
Ejemplo n.º 19
0
    def test_too_low_iteration_count(self):
        smmock = aiosasl.SASLStateMachine(SASLInterfaceMock(
            self,
            [
                ("auth;SCRAM-SHA-1",
                 b"n,,"+self.client_first_message_bare,
                 "challenge",
                 self.server_first_message.replace(b",i=4096", b",i=4095")),
                ("abort", None,
                 "failure", ("aborted", None)),
            ]))

        with self.assertRaisesRegexp(
                aiosasl.SASLFailure,
                r"minimum iteration count for SCRAM-SHA-1 violated "
                r"\(4095 is less than 4096\)") as ctx:
            self._run(smmock, aiosasl.SCRAM(self._provide_credentials))

        self.assertEqual(
            None,
            ctx.exception.opaque_error
        )
Ejemplo n.º 20
0
    def test_reject_protocol_violation_1(self):
        smmock = aiosasl.SASLStateMachine(SASLInterfaceMock(
            self,
            [
                ("auth;SCRAM-SHA-1",
                 b"n,,"+self.client_first_message_bare,
                 "challenge",
                 self.server_first_message),
                ("response",
                 self.client_final_message_without_proof +
                     b",p="+base64.b64encode(self.client_proof),
                 "success",
                 None),
            ]))

        with self.assertRaisesRegexp(aiosasl.SASLFailure,
                                     "protocol violation") as ctx:
            self._run(smmock, aiosasl.SCRAM(self._provide_credentials))

        self.assertEqual(
            "malformed-request",
            ctx.exception.opaque_error
        )