def protocol(): proto = CredReceiver() proto.portal = Portal( self.loginSystem, [self.loginSystem, OneTimePadChecker(self._oneTimePads)]) return proto
def setUp(self): """ Create a L{CredReceiver} hooked up to a fake L{IBoxSender} which records boxes sent through it. """ self.username = '******' self.password = '******' self.checker = InMemoryUsernamePasswordDatabaseDontUse() self.checker.addUser(self.username, self.password) self.avatar = StubAvatar() self.realm = StubRealm(self.avatar) self.portal = Portal(self.realm, [self.checker]) self.server = CredReceiver() self.server.portal = self.portal self.client = AMP() self.finished = loopbackAsync(self.server, self.client)
class CredReceiverTests(TestCase): """ Tests for L{CredReceiver}, an L{IBoxReceiver} which integrates with L{twisted.cred} to provide authentication and authorization of AMP connections. """ def setUp(self): """ Create a L{CredReceiver} hooked up to a fake L{IBoxSender} which records boxes sent through it. """ self.username = '******' self.password = '******' self.checker = InMemoryUsernamePasswordDatabaseDontUse() self.checker.addUser(self.username, self.password) self.avatar = StubAvatar() self.realm = StubRealm(self.avatar) self.portal = Portal(self.realm, [self.checker]) self.server = CredReceiver() self.server.portal = self.portal self.client = AMP() self.finished = loopbackAsync(self.server, self.client) def test_otpLogin(self): """ L{CredReceiver.otpLogin} returns without error if the pad is valid. """ PAD = 'test_otpLogin' self.portal.registerChecker(OneTimePadChecker({PAD: 'user'})) d = self.server.otpLogin(PAD) def cbLoggedIn(result): self.assertEqual(result, {}) d.addCallback(cbLoggedIn) return d def test_otpLoginUnauthorized(self): """ L{CredReceiver.otpLogin} should fail with L{UnauthorizedLogin} if an invalid pad is received. """ self.portal.registerChecker(OneTimePadChecker({})) return self.assertFailure( self.server.otpLogin('test_otpLoginUnauthorized'), UnauthorizedLogin) def test_otpLoginNotImplemented(self): """ L{CredReceiver.otpLogin} should fail with L{NotImplementedError} if the realm raises L{NotImplementedError} when asked for the avatar. """ def noAvatar(avatarId, mind, *interfaces): raise NotImplementedError() self.realm.requestAvatar = noAvatar PAD = 'test_otpLoginNotImplemented' self.portal.registerChecker(OneTimePadChecker({PAD: 'user'})) return self.assertFailure( self.server.otpLogin(PAD), NotImplementedError) def test_otpLoginResponder(self): """ L{CredReceiver} responds to the L{OTPLogin} command. """ PAD = 'test_otpLoginResponder' self.portal.registerChecker(OneTimePadChecker({PAD: 'user'})) d = self.client.callRemote(OTPLogin, pad=PAD) def cbLoggedIn(result): self.assertEqual(result, {}) d.addCallback(cbLoggedIn) return d def test_passwordLoginDifferentChallenges(self): """ L{CredReceiver.passwordLogin} returns a new challenge each time it is called. """ first = self.server.passwordLogin(self.username) second = self.server.passwordLogin(self.username) self.assertNotEqual(first['challenge'], second['challenge']) def test_passwordLoginResponder(self): """ L{CredReceiver} responds to the L{PasswordLogin} L{Command} with a challenge. """ d = self.client.callRemote(PasswordLogin, username=self.username) def cbLogin(result): self.assertIn('challenge', result) d.addCallback(cbLogin) return d def test_determineFromDifferentNonces(self): """ Each time L{PasswordChallengeResponse.determineFrom} is used, it generates a different C{cnonce} value. """ first = PasswordChallengeResponse.determineFrom('a', 'b') second = PasswordChallengeResponse.determineFrom('a', 'b') self.assertNotEqual(first['cnonce'], second['cnonce']) def test_passwordChallengeResponse(self): """ L{CredReceiver.passwordChallengeResponse} returns without error if the response is valid. """ challenge = self.server.passwordLogin(self.username)['challenge'] cnonce = '123abc' cleartext = '%s %s %s' % (challenge, cnonce, self.password) response = sha1(cleartext).digest() d = self.server.passwordChallengeResponse(cnonce, response) def cbLoggedIn(result): self.assertEqual(result, {}) d.addCallback(cbLoggedIn) return d def test_passwordChallengeResponseResponder(self): """ L{CredReceiver} responds to the L{PasswordChallengeResponse} L{Command} with an empty box if the response supplied is valid. """ challenge = self.server.passwordLogin(self.username)['challenge'] d = self.client.callRemote( PasswordChallengeResponse, **PasswordChallengeResponse.determineFrom( challenge, self.password)) def cbResponded(result): self.assertEqual(result, {}) d.addCallback(cbResponded) return d def test_response(self): """ L{PasswordChallengeResponse.determineFrom} generates the correct response to a challenge issued by L{CredReceiver.passwordLogin}. """ challenge = self.server.passwordLogin(self.username)['challenge'] result = PasswordChallengeResponse.determineFrom( challenge, self.password) d = self.server.passwordChallengeResponse(**result) def cbLoggedIn(ignored): [(avatarId, mind, interfaces)] = self.realm.requests self.assertEqual(avatarId, self.username) self.assertEqual(interfaces, (IBoxReceiver,)) # The avatar is now the protocol's box receiver. self.assertIdentical(self.server.boxReceiver, self.avatar) # And the avatar has been started up with the protocol's # IBoxSender. self.assertIdentical(self.avatar.boxSender, self.server.boxSender) # After the connection is lost, the logout function should be # called. self.assertEqual(self.realm.loggedOut, 0) self.server.connectionLost( Failure(ConnectionDone("test connection lost"))) self.assertEqual(self.realm.loggedOut, 1) d.addCallback(cbLoggedIn) return d def test_invalidResponse(self): """ L{CredReceiver.passwordChallengeResponse} returns a L{Deferred} which fails with L{UnauthorizedLogin} if it is passed a response which is not valid. """ challenge = self.server.passwordLogin(self.username)['challenge'] return self.assertFailure( self.server.passwordChallengeResponse(cnonce='bar', response='baz'), UnauthorizedLogin) def test_connectionLostWithoutAvatar(self): """ L{CredReceiver.connectionLost} does not raise an exception if no login has occurred when it is called. """ self.server.connectionLost( Failure(ConnectionDone("test connection lost"))) def test_unrecognizedCredentialsLogin(self): """ L{login} raises L{UnhandledCredentials} if passed a credentials object which provides no interface explicitly supported by that function, currently L{IUsernamePassword}. """ self.assertRaises(UnhandledCredentials, login, None, None) def test_passwordChallengeLogin(self): """ L{login} issues the commands necessary to authenticate against L{CredReceiver} when given an L{IUsernamePassword} provider with its C{username} and C{password} attributes set to valid credentials. """ loginDeferred = login( self.client, UsernamePassword(self.username, self.password)) def cbLoggedIn(clientAgain): self.assertIdentical(self.client, clientAgain) self.assertIdentical(self.server.boxReceiver, self.avatar) loginDeferred.addCallback(cbLoggedIn) return loginDeferred def test_passwordChallengeInvalid(self): """ L{login} returns a L{Deferred} which fires with L{UnauthorizedLogin} if the L{UsernamePassword} credentials object given does not contain valid authentication information. """ boxReceiver = self.server.boxReceiver loginDeferred = login( self.client, UsernamePassword(self.username + 'x', self.password)) self.assertFailure(loginDeferred, UnauthorizedLogin) def cbFailed(ignored): self.assertIdentical(self.server.boxReceiver, boxReceiver) loginDeferred.addCallback(cbFailed) return loginDeferred def test_noAvatar(self): """ L{login} returns a L{Deferred} which fires with L{NotImplementedError} if the realm raises L{NotImplementedError} when asked for the avatar. """ def noAvatar(avatarId, mind, *interfaces): raise NotImplementedError() self.realm.requestAvatar = noAvatar loginDeferred = login( self.client, UsernamePassword(self.username, self.password)) return self.assertFailure(loginDeferred, NotImplementedError)
class CredReceiverTests(TestCase): """ Tests for L{CredReceiver}, an L{IBoxReceiver} which integrates with L{twisted.cred} to provide authentication and authorization of AMP connections. """ def setUp(self): """ Create a L{CredReceiver} hooked up to a fake L{IBoxSender} which records boxes sent through it. """ self.username = '******' self.password = '******' self.checker = InMemoryUsernamePasswordDatabaseDontUse() self.checker.addUser(self.username, self.password) self.avatar = StubAvatar() self.realm = StubRealm(self.avatar) self.portal = Portal(self.realm, [self.checker]) self.server = CredReceiver() self.server.portal = self.portal self.client = AMP() self.finished = loopbackAsync(self.server, self.client) def test_otpLogin(self): """ L{CredReceiver.otpLogin} returns without error if the pad is valid. """ PAD = 'test_otpLogin' self.portal.registerChecker(OneTimePadChecker({PAD: 'user'})) d = self.server.otpLogin(PAD) def cbLoggedIn(result): self.assertEqual(result, {}) d.addCallback(cbLoggedIn) return d def test_otpLoginUnauthorized(self): """ L{CredReceiver.otpLogin} should fail with L{UnauthorizedLogin} if an invalid pad is received. """ self.portal.registerChecker(OneTimePadChecker({})) return self.assertFailure( self.server.otpLogin('test_otpLoginUnauthorized'), UnauthorizedLogin) def test_otpLoginNotImplemented(self): """ L{CredReceiver.otpLogin} should fail with L{NotImplementedError} if the realm raises L{NotImplementedError} when asked for the avatar. """ def noAvatar(avatarId, mind, *interfaces): raise NotImplementedError() self.realm.requestAvatar = noAvatar PAD = 'test_otpLoginNotImplemented' self.portal.registerChecker(OneTimePadChecker({PAD: 'user'})) return self.assertFailure(self.server.otpLogin(PAD), NotImplementedError) def test_otpLoginResponder(self): """ L{CredReceiver} responds to the L{OTPLogin} command. """ PAD = 'test_otpLoginResponder' self.portal.registerChecker(OneTimePadChecker({PAD: 'user'})) d = self.client.callRemote(OTPLogin, pad=PAD) def cbLoggedIn(result): self.assertEqual(result, {}) d.addCallback(cbLoggedIn) return d def test_passwordLoginDifferentChallenges(self): """ L{CredReceiver.passwordLogin} returns a new challenge each time it is called. """ first = self.server.passwordLogin(self.username) second = self.server.passwordLogin(self.username) self.assertNotEqual(first['challenge'], second['challenge']) def test_passwordLoginResponder(self): """ L{CredReceiver} responds to the L{PasswordLogin} L{Command} with a challenge. """ d = self.client.callRemote(PasswordLogin, username=self.username) def cbLogin(result): self.assertIn('challenge', result) d.addCallback(cbLogin) return d def test_determineFromDifferentNonces(self): """ Each time L{PasswordChallengeResponse.determineFrom} is used, it generates a different C{cnonce} value. """ first = PasswordChallengeResponse.determineFrom('a', 'b') second = PasswordChallengeResponse.determineFrom('a', 'b') self.assertNotEqual(first['cnonce'], second['cnonce']) def test_passwordChallengeResponse(self): """ L{CredReceiver.passwordChallengeResponse} returns without error if the response is valid. """ challenge = self.server.passwordLogin(self.username)['challenge'] cnonce = '123abc' cleartext = '%s %s %s' % (challenge, cnonce, self.password) response = sha1(cleartext).digest() d = self.server.passwordChallengeResponse(cnonce, response) def cbLoggedIn(result): self.assertEqual(result, {}) d.addCallback(cbLoggedIn) return d def test_passwordChallengeResponseResponder(self): """ L{CredReceiver} responds to the L{PasswordChallengeResponse} L{Command} with an empty box if the response supplied is valid. """ challenge = self.server.passwordLogin(self.username)['challenge'] d = self.client.callRemote( PasswordChallengeResponse, **PasswordChallengeResponse.determineFrom(challenge, self.password)) def cbResponded(result): self.assertEqual(result, {}) d.addCallback(cbResponded) return d def test_response(self): """ L{PasswordChallengeResponse.determineFrom} generates the correct response to a challenge issued by L{CredReceiver.passwordLogin}. """ challenge = self.server.passwordLogin(self.username)['challenge'] result = PasswordChallengeResponse.determineFrom( challenge, self.password) d = self.server.passwordChallengeResponse(**result) def cbLoggedIn(ignored): [(avatarId, mind, interfaces)] = self.realm.requests self.assertEqual(avatarId, self.username) self.assertEqual(interfaces, (IBoxReceiver, )) # The avatar is now the protocol's box receiver. self.assertIdentical(self.server.boxReceiver, self.avatar) # And the avatar has been started up with the protocol's # IBoxSender. self.assertIdentical(self.avatar.boxSender, self.server.boxSender) # After the connection is lost, the logout function should be # called. self.assertEqual(self.realm.loggedOut, 0) self.server.connectionLost( Failure(ConnectionDone("test connection lost"))) self.assertEqual(self.realm.loggedOut, 1) d.addCallback(cbLoggedIn) return d def test_invalidResponse(self): """ L{CredReceiver.passwordChallengeResponse} returns a L{Deferred} which fails with L{UnauthorizedLogin} if it is passed a response which is not valid. """ challenge = self.server.passwordLogin(self.username)['challenge'] return self.assertFailure( self.server.passwordChallengeResponse(cnonce='bar', response='baz'), UnauthorizedLogin) def test_connectionLostWithoutAvatar(self): """ L{CredReceiver.connectionLost} does not raise an exception if no login has occurred when it is called. """ self.server.connectionLost( Failure(ConnectionDone("test connection lost"))) def test_unrecognizedCredentialsLogin(self): """ L{login} raises L{UnhandledCredentials} if passed a credentials object which provides no interface explicitly supported by that function, currently L{IUsernamePassword}. """ self.assertRaises(UnhandledCredentials, login, None, None) def test_passwordChallengeLogin(self): """ L{login} issues the commands necessary to authenticate against L{CredReceiver} when given an L{IUsernamePassword} provider with its C{username} and C{password} attributes set to valid credentials. """ loginDeferred = login(self.client, UsernamePassword(self.username, self.password)) def cbLoggedIn(clientAgain): self.assertIdentical(self.client, clientAgain) self.assertIdentical(self.server.boxReceiver, self.avatar) loginDeferred.addCallback(cbLoggedIn) return loginDeferred def test_passwordChallengeInvalid(self): """ L{login} returns a L{Deferred} which fires with L{UnauthorizedLogin} if the L{UsernamePassword} credentials object given does not contain valid authentication information. """ boxReceiver = self.server.boxReceiver loginDeferred = login( self.client, UsernamePassword(self.username + 'x', self.password)) self.assertFailure(loginDeferred, UnauthorizedLogin) def cbFailed(ignored): self.assertIdentical(self.server.boxReceiver, boxReceiver) loginDeferred.addCallback(cbFailed) return loginDeferred def test_noAvatar(self): """ L{login} returns a L{Deferred} which fires with L{NotImplementedError} if the realm raises L{NotImplementedError} when asked for the avatar. """ def noAvatar(avatarId, mind, *interfaces): raise NotImplementedError() self.realm.requestAvatar = noAvatar loginDeferred = login(self.client, UsernamePassword(self.username, self.password)) return self.assertFailure(loginDeferred, NotImplementedError)