diff --git a/authserv/test/__init__.py b/authserv/test/__init__.py index fbd6bf86a7d95c9261dad079252b40c620e4bc06..d05b74e85bf5206a4d6d298daa3e122a43797e26 100644 --- a/authserv/test/__init__.py +++ b/authserv/test/__init__.py @@ -1,6 +1,10 @@ import crypt +import logging +import os +import socket import time import unittest +from ldap_test import LdapServer from authserv import model @@ -67,3 +71,41 @@ class FakeUserDb(model.UserDb): def get_user(self, username, service): return self.users.get(username) + +class LdapTestBase(unittest.TestCase): + + LDIFS = [] + + @classmethod + def _pick_free_port(cls): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.bind(('', 0)) + port = sock.getsockname()[1] + sock.close() + return port + + @classmethod + def setup_class(cls): + # Start the local LDAP server. + cls.ldap_port = cls._pick_free_port() + cls.ldap_password = 'testpass' + ldifs = [os.path.join(os.path.dirname(__file__), 'fixtures', x) + for x in ['base.ldif'] + cls.LDIFS] + logging.getLogger('py4j.java_gateway').setLevel(logging.ERROR) + cls.server = LdapServer({ + 'port': cls.ldap_port, + 'bind_dn': 'cn=manager,o=Anarchy', + 'password': cls.ldap_password, + 'base': { + 'objectclass': ['organization'], + 'dn': 'o=Anarchy', + 'attributes': {'o': 'Anarchy'}, + }, + 'ldifs': ldifs, + }) + cls.server.start() + + @classmethod + def teardown_class(cls): + cls.server.stop() + diff --git a/authserv/test/fixtures/base.ldif b/authserv/test/fixtures/base.ldif new file mode 100644 index 0000000000000000000000000000000000000000..619959c3f83742bedacb5d5e4c2d7373a422af5e --- /dev/null +++ b/authserv/test/fixtures/base.ldif @@ -0,0 +1,96 @@ +dn: o=Anarchy +changetype: add +o: Anarchy +objectClass: top +objectClass: organization + +dn: dc=org,o=Anarchy +changetype: add +dc: org +objectClass: top +objectClass: domain + +dn: dc=investici,dc=org,o=Anarchy +changetype: add +dc: investici +objectClass: top +objectClass: domain + +dn: ou=People,dc=investici,dc=org,o=Anarchy +changetype: add +ou: People +objectClass: top +objectClass: organizationalUnit +description: Investici people + +dn: ou=Categories,dc=investici,dc=org,o=Anarchy +changetype: add +ou: Categories +objectClass: top +objectClass: organizationalUnit +description: Site categories + +dn: ou=Operators,dc=investici,dc=org,o=Anarchy +changetype: add +ou: Operators +objectClass: top +objectClass: organizationalUnit +description: Autonomous software agents + +dn: ou=Group,dc=investici,dc=org,o=Anarchy +changetype: add +ou: Group +objectClass: organizationalUnit + +dn: ou=Lists,dc=investici,dc=org,o=Anarchy +changetype: add +ou: Lists +objectClass: top +objectClass: organizationalUnit +description: Mailing Lists + +dn: ou=Newsletters,dc=investici,dc=org,o=Anarchy +changetype: add +ou: Newsletters +objectClass: top +objectClass: organizationalUnit +description: Newsletters + +dn: ou=Domains,dc=investici,dc=org,o=Anarchy +changetype: add +ou: Domains +objectClass: top +objectClass: organizationalUnit +description: Investici domains + +dn: cn=autistici.org,ou=Domains,dc=investici,dc=org,o=Anarchy +changetype: add +cn: autistici.org +objectClass: top +objectClass: investiciDomain +acceptMail: true +public: yes + +dn: cn=inventati.org,ou=Domains,dc=investici,dc=org,o=Anarchy +changetype: add +cn: inventati.org +objectClass: top +objectClass: investiciDomain +acceptMail: true +public: yes + +dn: cn=investici.org,ou=Domains,dc=investici,dc=org,o=Anarchy +changetype: add +cn: investici.org +objectClass: top +objectClass: investiciDomain +acceptMail: true +public: no + +dn: cn=anche.no,ou=Domains,dc=investici,dc=org,o=Anarchy +changetype: add +cn: anche.no +objectClass: top +objectClass: investiciDomain +acceptMail: true +public: yes diff --git a/authserv/test/fixtures/test-user-totp.ldif b/authserv/test/fixtures/test-user-totp.ldif new file mode 100644 index 0000000000000000000000000000000000000000..4e917dbed644a4296878ae260f40030d087248c3 --- /dev/null +++ b/authserv/test/fixtures/test-user-totp.ldif @@ -0,0 +1,42 @@ +dn: uid=test@investici.org,ou=People,dc=investici,dc=org,o=Anarchy +changetype: add +cn: test@investici.org +objectClass: top +objectClass: person +objectClass: posixAccount +objectClass: shadowAccount +objectClass: organizationalPerson +objectClass: inetOrgPerson +loginShell: /bin/false +uidNumber: 19475 +shadowMax: 99999 +preferredLanguage: en +gidNumber: 2000 +gecos: test@investici.org +sn: Private +homeDirectory: /var/empty +uid: test@investici.org +givenName: Private +shadowLastChange: 12345 +shadowWarning: 7 +userPassword:: e2NyeXB0fXp6WFVIZlVSbkdnOEk= + +dn: mail=test@investici.org,uid=test@investici.org,ou=People,dc=investici,dc=org,o=Anarchy +changetype: add +status: active +objectClass: top +objectClass: virtualMailUser +uidNumber: 19475 +host: latitanza +mailAlternateAddress: test@anche.no +gidNumber: 2000 +mail: test@investici.org +creationDate: 2013-12-31 +mailMessageStore: investici.org/test/ +originalHost: latitanza +userPassword:: e2NyeXB0fXp6WFVIZlVSbkdnOEk= +recoverQuestion: question +recoverAnswer:: e2NyeXB0fWFhd1IuamRHTVIwMTY= +totpSecret: 089421 +appSpecificPassword:: bWFpbDokMSQkNXp2RTI5emVIOVc3S0sweVRPMERaMQ== + diff --git a/authserv/test/fixtures/test-user.ldif b/authserv/test/fixtures/test-user.ldif new file mode 100644 index 0000000000000000000000000000000000000000..ffae59b42d43a8dd8542e14471beb04faf965bc3 --- /dev/null +++ b/authserv/test/fixtures/test-user.ldif @@ -0,0 +1,39 @@ +dn: uid=test@investici.org,ou=People,dc=investici,dc=org,o=Anarchy +changetype: add +cn: test@investici.org +objectClass: top +objectClass: person +objectClass: posixAccount +objectClass: shadowAccount +objectClass: organizationalPerson +objectClass: inetOrgPerson +loginShell: /bin/false +uidNumber: 19475 +shadowMax: 99999 +preferredLanguage: en +gidNumber: 2000 +gecos: test@investici.org +sn: Private +homeDirectory: /var/empty +uid: test@investici.org +givenName: Private +shadowLastChange: 12345 +shadowWarning: 7 +userPassword:: e2NyeXB0fXp6WFVIZlVSbkdnOEk= + +dn: mail=test@investici.org,uid=test@investici.org,ou=People,dc=investici,dc=org,o=Anarchy +changetype: add +status: active +objectClass: top +objectClass: virtualMailUser +uidNumber: 19475 +host: latitanza +mailAlternateAddress: test@anche.no +gidNumber: 2000 +mail: test@investici.org +creationDate: 2013-12-31 +mailMessageStore: investici.org/test/ +originalHost: latitanza +userPassword:: e2NyeXB0fXp6WFVIZlVSbkdnOEk= +recoverQuestion: question +recoverAnswer:: e2NyeXB0fWFhd1IuamRHTVIwMTY= \ No newline at end of file diff --git a/authserv/test/test_auth_ldap.py b/authserv/test/test_auth_ldap.py new file mode 100644 index 0000000000000000000000000000000000000000..9e72a4c3d67e43e453a7befd5d2677fed6030f85 --- /dev/null +++ b/authserv/test/test_auth_ldap.py @@ -0,0 +1,97 @@ +from authserv.test import * +from authserv.auth import authenticate +from authserv import ldap_model +from authserv import protocol +from authserv.oath import totp + + +class LdapAuthTestBase(LdapTestBase): + + SERVICE_MAP = { + 'mail': { + 'base': 'ou=People,dc=investici,dc=org,o=Anarchy', + 'filter': '(&(status=active)(mail=%s))', + }, + } + + def setUp(self): + self.userdb = ldap_model.UserDb( + self.SERVICE_MAP, + 'ldap://localhost:%d' % self.ldap_port, + 'cn=manager,o=Anarchy', + self.ldap_password) + + +class LdapAuthTest(LdapAuthTestBase): + + LDIFS = [ + 'test-user.ldif', + ] + + def test_auth_password_ok(self): + u = self.userdb.get_user('test@investici.org', 'mail') + self.assertTrue(u) + self.assertEquals( + protocol.OK, + authenticate(u, 'mail', 'password', None)) + + def test_auth_password_fail(self): + u = self.userdb.get_user('test@investici.org', 'mail') + self.assertTrue(u) + self.assertEquals( + protocol.ERR_AUTHENTICATION_FAILURE, + authenticate(u, 'mail', 'wrong password', None)) + + +class LdapOtpTest(LdapAuthTestBase): + + LDIFS = [ + 'test-user-totp.ldif', + ] + + def test_auth_password_requires_otp(self): + u = self.userdb.get_user('test@investici.org', 'mail') + self.assertTrue(u) + self.assertEquals( + protocol.ERR_OTP_REQUIRED, + authenticate(u, 'mail', 'password', None)) + + def test_auth_bad_password_requires_otp(self): + u = self.userdb.get_user('test@investici.org', 'mail') + self.assertTrue(u) + self.assertEquals( + protocol.ERR_OTP_REQUIRED, + authenticate(u, 'mail', 'wrong password', None)) + + def test_auth_otp_ok(self): + u = self.userdb.get_user('test@investici.org', 'mail') + self.assertTrue(u) + secret= '089421' + token = totp(secret, format='dec6', period=30) + self.assertEquals( + protocol.OK, + authenticate(u, 'mail', 'password', str(token))) + + def test_auth_otp_ok_bad_password(self): + u = self.userdb.get_user('test@investici.org', 'mail') + self.assertTrue(u) + secret= '089421' + token = totp(secret, format='dec6', period=30) + self.assertEquals( + protocol.ERR_AUTHENTICATION_FAILURE, + authenticate(u, 'mail', 'wrong password', str(token))) + + def test_auth_bad_otp(self): + u = self.userdb.get_user('test@investici.org', 'mail') + self.assertTrue(u) + self.assertEquals( + protocol.ERR_AUTHENTICATION_FAILURE, + authenticate(u, 'mail', 'password', '123456')) + + def test_app_specific_password(self): + u = self.userdb.get_user('test@investici.org', 'mail') + self.assertTrue(u) + self.assertEquals( + protocol.OK, + authenticate(u, 'mail', 'veryspecificpassword', None)) +