diff --git a/Lib/slapdtest.py b/Lib/slapdtest.py index b5e1507..e0e57c7 100644 --- a/Lib/slapdtest.py +++ b/Lib/slapdtest.py @@ -43,6 +43,11 @@ TLSCertificateKeyFile "%(serverkey)s" # ignore missing client cert but fail with invalid client cert TLSVerifyClient try + +authz-regexp + "C=DE, O=python-ldap, OU=slapd-test, CN=([A-Za-z]+)" + "ldap://ou=people,dc=local???($1)" + """ LOCALHOST = '127.0.0.1' @@ -289,6 +294,7 @@ def _start_slapd(self): slapd_args = [ self.PATH_SLAPD, '-f', self._slapd_conf, + '-F', self.testrundir, '-h', '%s' % ' '.join((self.ldap_uri, self.ldapi_uri)), ] if self._log.isEnabledFor(logging.DEBUG): diff --git a/Tests/t_cext.py b/Tests/t_cext.py index 3a0f7df..22eb895 100644 --- a/Tests/t_cext.py +++ b/Tests/t_cext.py @@ -835,7 +835,6 @@ def test_tls_ext_clientcert(self): l.set_option(_ldap.OPT_X_TLS_REQUIRE_CERT, _ldap.OPT_X_TLS_HARD) l.set_option(_ldap.OPT_X_TLS_NEWCTX, 0) l.start_tls_s() - # TODO verify that client auth actually works if __name__ == '__main__': unittest.main() diff --git a/Tests/t_ldap_sasl.py b/Tests/t_ldap_sasl.py new file mode 100644 index 0000000..e689bb6 --- /dev/null +++ b/Tests/t_ldap_sasl.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- +""" +Automatic tests for python-ldap's module ldap.sasl + +See http://www.python-ldap.org/ for details. +""" +import os +import pwd +import socket +import unittest + +# Switch off processing .ldaprc or ldap.conf before importing _ldap +os.environ['LDAPNOINIT'] = '1' + +from ldap.ldapobject import SimpleLDAPObject +import ldap.sasl +from slapdtest import SlapdTestCase + + +LDIF = """ +dn: {suffix} +objectClass: dcObject +objectClass: organization +dc: {dc} +o: {dc} + +dn: {rootdn} +objectClass: applicationProcess +objectClass: simpleSecurityObject +objectClass: uidObject +cn: {rootcn} +userPassword: {rootpw} +uid: {uid} + +dn: cn={certuser},{suffix} +objectClass: applicationProcess +cn: {certuser} + +""" + + +class TestSasl(SlapdTestCase): + ldap_object_class = SimpleLDAPObject + # from Tests/certs/client.pem + certuser = 'client' + certsubject = "cn=client,ou=slapd-test,o=python-ldap,c=de" + + @classmethod + def setUpClass(cls): + super(TestSasl, cls).setUpClass() + ldif = LDIF.format( + suffix=cls.server.suffix, + rootdn=cls.server.root_dn, + rootcn=cls.server.root_cn, + rootpw=cls.server.root_pw, + dc=cls.server.suffix.split(',')[0][3:], + certuser=cls.certuser, + uid=os.geteuid(), + ) + cls.server.ldapadd(ldif) + + @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), "needs Unix socket") + def test_external_ldapi(self): + # EXTERNAL authentication with LDAPI (AF_UNIX) + ldap_conn = self.ldap_object_class(self.server.ldapi_uri) + + auth = ldap.sasl.external("some invalid user") + with self.assertRaises(ldap.INSUFFICIENT_ACCESS): + ldap_conn.sasl_interactive_bind_s("", auth) + + auth = ldap.sasl.external("") + ldap_conn.sasl_interactive_bind_s("", auth) + self.assertEqual( + ldap_conn.whoami_s().lower(), + "dn:{}".format(self.server.root_dn.lower()) + ) + + def test_external_tlscert(self): + ldap_conn = self.ldap_object_class(self.server.ldap_uri) + ldap_conn.set_option(ldap.OPT_X_TLS_CACERTFILE, self.server.cafile) + ldap_conn.set_option(ldap.OPT_X_TLS_CERTFILE, self.server.clientcert) + ldap_conn.set_option(ldap.OPT_X_TLS_KEYFILE, self.server.clientkey) + ldap_conn.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_HARD) + ldap_conn.set_option(ldap.OPT_X_TLS_NEWCTX, 0) + ldap_conn.start_tls_s() + + auth = ldap.sasl.external() + ldap_conn.sasl_interactive_bind_s("", auth) + self.assertEqual( + ldap_conn.whoami_s().lower(), + "dn:{}".format(self.certsubject) + ) + +if __name__ == '__main__': + unittest.main() +