From 57ed6aece2ddcc307e99e88c2a32548bed80b1b9 Mon Sep 17 00:00:00 2001 From: SOMA Yuki Date: Thu, 2 Aug 2018 18:39:01 +0900 Subject: [PATCH 1/9] Attach response controls to exceptions --- Doc/reference/ldap.rst | 1 + Doc/reference/slapdtest.rst | 6 +++ Lib/slapdtest/__init__.py | 5 ++- Lib/slapdtest/_slapdtest.py | 71 +++++++++++++++++++++++++++++++- Modules/LDAPObject.c | 30 ++++++++------ Modules/constants.c | 18 +++++++- Modules/constants.h | 1 + Tests/t_ldap_controls_ppolicy.py | 6 +++ Tests/t_ldapobject.py | 71 +++++++++++++++++++++++++++++++- 9 files changed, 190 insertions(+), 19 deletions(-) diff --git a/Doc/reference/ldap.rst b/Doc/reference/ldap.rst index 0ce2e418..d9e0c5da 100644 --- a/Doc/reference/ldap.rst +++ b/Doc/reference/ldap.rst @@ -316,6 +316,7 @@ The module defines the following exceptions: is set to a truncated form of the name provided or alias dereferenced for the lowest entry (object or alias) that was matched. + The :py:const:`ctrls` field can be included to the dictionary, which is a list of response controls. .. py:exception:: ADMINLIMIT_EXCEEDED diff --git a/Doc/reference/slapdtest.rst b/Doc/reference/slapdtest.rst index bd54bb69..824c5dd9 100644 --- a/Doc/reference/slapdtest.rst +++ b/Doc/reference/slapdtest.rst @@ -26,3 +26,9 @@ Classes .. autoclass:: slapdtest.SlapdTestCase :members: + +.. autoclass:: slapdtest.PPolicyEnabledSlapdObject + :members: + +.. autoclass:: slapdtest.PPolicyEnabledSlapdTestCase + :members: diff --git a/Lib/slapdtest/__init__.py b/Lib/slapdtest/__init__.py index 56ba2c91..567e666b 100644 --- a/Lib/slapdtest/__init__.py +++ b/Lib/slapdtest/__init__.py @@ -7,6 +7,9 @@ __version__ = '3.1.0' -from slapdtest._slapdtest import SlapdObject, SlapdTestCase, SysLogHandler +from slapdtest._slapdtest import ( + SlapdObject, SlapdTestCase, + PPolicyEnabledSlapdObject, PPolicyEnabledSlapdTestCase, + SysLogHandler) from slapdtest._slapdtest import requires_ldapi, requires_sasl, requires_tls from slapdtest._slapdtest import skip_unless_ci diff --git a/Lib/slapdtest/_slapdtest.py b/Lib/slapdtest/_slapdtest.py index f1885caf..93e9d0a2 100644 --- a/Lib/slapdtest/_slapdtest.py +++ b/Lib/slapdtest/_slapdtest.py @@ -27,7 +27,9 @@ # a template string for generating simple slapd.conf file SLAPD_CONF_TEMPLATE = r""" + serverID %(serverid)s +%(moduleload_directives)s moduleload back_%(database)s %(include_directives)s loglevel %(loglevel)s @@ -43,6 +45,8 @@ rootdn "%(rootdn)s" rootpw "%(rootpw)s" +%(overlay_configurations)s + TLSCACertificateFile "%(cafile)s" TLSCertificateFile "%(servercert)s" TLSCertificateKeyFile "%(serverkey)s" @@ -187,6 +191,9 @@ class SlapdObject(object): 'core.schema', ) + modules = () + overlays = () + TMPDIR = os.environ.get('TMP', os.getcwd()) if 'SCHEMA' in os.environ: SCHEMADIR = os.environ['SCHEMA'] @@ -331,9 +338,22 @@ def gen_config(self): ) for schema_file in self.openldap_schema_files ) + + moduleload_directives = '\n'.join( + "moduleload {module}".format(module=module) + for module in self.modules + ) + + overlay_configurations = '\n'.join( + "overlay {name}\n{configuration}".format(**overlay) + for overlay in self.overlays + ) + config_dict = { 'serverid': hex(self.server_id), 'schema_prefix':self._schema_prefix, + 'moduleload_directives': moduleload_directives, + 'overlay_configurations': overlay_configurations, 'include_directives': include_directives, 'loglevel': self.slapd_loglevel, 'database': self.database, @@ -582,10 +602,17 @@ def _open_ldap_conn(self, who=None, cred=None, **kwargs): """ return a LDAPObject instance after simple bind """ + ldap_conn = self._make_ldap_object(**kwargs) + ldap_conn.simple_bind_s(who or self.server.root_dn, cred or self.server.root_pw) + return ldap_conn + + def _make_ldap_object(self, **kwargs): + """ + return an unbound LDAPObject instance with common ldap options. + """ ldap_conn = self.ldap_object_class(self.server.ldap_uri, **kwargs) ldap_conn.protocol_version = 3 - #ldap_conn.set_option(ldap.OPT_REFERRALS, 0) - ldap_conn.simple_bind_s(who or self.server.root_dn, cred or self.server.root_pw) + # ldap_conn.set_option(ldap.OPT_REFERRALS, 0) return ldap_conn @classmethod @@ -596,3 +623,43 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): cls.server.stop() + + +class PPolicyEnabledSlapdObject(SlapdObject): + """ + A subclass of :py:class:`SlapdObject` with password policy enabled. + Note that this class has no actual password policy configuration entries. + It is the job of the users of this class to define + the default password policies on their own. + The dn of the default is :attr:`.default_ppolicy_dn` of this class. + """ + + openldap_schema_files = ( + 'core.schema', 'ppolicy.schema' + ) + modules = ( + 'ppolicy', + ) + + default_ppolicy_dn = "cn=default-ppolicy,%(suffix)s" % { + 'suffix': SlapdObject.suffix + } + + overlays = ( + { + 'name': 'ppolicy', + 'configuration': "\n".join([ + 'ppolicy_default "{}"'.format(default_ppolicy_dn), + # let slapd tell the clients that they are locked out + 'ppolicy_use_lockout']) + }, + ) + + +class PPolicyEnabledSlapdTestCase(SlapdTestCase): + """ + A subclass of :py:class:`SlapdTestCase`, which uses + :py:class:`PPolicyEnabledSlapdObject` as the slapd controller. + """ + + server_class = PPolicyEnabledSlapdObject diff --git a/Modules/LDAPObject.c b/Modules/LDAPObject.c index bc26727e..0d980959 100644 --- a/Modules/LDAPObject.c +++ b/Modules/LDAPObject.c @@ -1162,6 +1162,20 @@ l_ldap_result4(LDAPObject *self, PyObject *args) LDAP_END_ALLOW_THREADS(self); } + if (!(pyctrls = LDAPControls_to_List(serverctrls))) { + int err = LDAP_NO_MEMORY; + + LDAP_BEGIN_ALLOW_THREADS(self); + ldap_set_option(self->ldap, LDAP_OPT_ERROR_NUMBER, &err); + LDAP_END_ALLOW_THREADS(self); + ldap_msgfree(msg); + Py_XDECREF(valuestr); + return LDAPerror(self->ldap, "LDAPControls_to_List"); + } + ldap_controls_free(serverctrls); + + /* Always call Py_XDECREF(pyctrls) before returning after here */ + if (result != LDAP_SUCCESS) { /* result error */ char *e, err[1024]; @@ -1173,21 +1187,11 @@ l_ldap_result4(LDAPObject *self, PyObject *args) e = "ldap_parse_result"; ldap_msgfree(msg); Py_XDECREF(valuestr); - return LDAPerror(self->ldap, e); + retval = LDAPraise_exception(self->ldap, e, pyctrls); + Py_XDECREF(pyctrls); + return retval; } - if (!(pyctrls = LDAPControls_to_List(serverctrls))) { - int err = LDAP_NO_MEMORY; - - LDAP_BEGIN_ALLOW_THREADS(self); - ldap_set_option(self->ldap, LDAP_OPT_ERROR_NUMBER, &err); - LDAP_END_ALLOW_THREADS(self); - ldap_msgfree(msg); - Py_XDECREF(valuestr); - return LDAPerror(self->ldap, "LDAPControls_to_List"); - } - ldap_controls_free(serverctrls); - pmsg = LDAPmessage_to_python(self->ldap, msg, add_ctrls, add_intermediates); diff --git a/Modules/constants.c b/Modules/constants.c index f8da3736..bcd5dff2 100644 --- a/Modules/constants.c +++ b/Modules/constants.c @@ -48,7 +48,7 @@ LDAPerr(int errnum) /* Convert an LDAP error into an informative python exception */ PyObject * -LDAPerror(LDAP *l, char *msg) +LDAPraise_exception(LDAP *l, char *msg, PyObject *pyctrls) { if (l == NULL) { PyErr_SetFromErrno(LDAPexception_class); @@ -104,6 +104,11 @@ LDAPerror(LDAP *l, char *msg) ldap_memfree(matched); } + if (pyctrls != NULL) { + PyDict_SetItemString(info, "ctrls", pyctrls); + /* Py_XDECREF(pyctrls) must be called on caller side */ + } + if (errnum == LDAP_REFERRAL) { str = PyUnicode_FromString(msg); if (str) @@ -125,6 +130,17 @@ LDAPerror(LDAP *l, char *msg) } } + +/* Convert an LDAP error into an informative python exception. + This is the convenient function for the case where the exception + doesn't have to include any response controls. */ +PyObject * +LDAPerror(LDAP *l, char *msg) +{ + return LDAPraise_exception(l, msg, NULL); +} + + /* initialise the module constants */ int diff --git a/Modules/constants.h b/Modules/constants.h index 8a390b5b..3b66c1d3 100644 --- a/Modules/constants.h +++ b/Modules/constants.h @@ -12,6 +12,7 @@ extern PyObject *LDAPconstant(int); extern PyObject *LDAPexception_class; extern PyObject *LDAPerror(LDAP *, char *msg); +extern PyObject *LDAPraise_exception(LDAP *, char *msg, PyObject *pyctrls); PyObject *LDAPerr(int errnum); #ifndef LDAP_CONTROL_PAGE_OID diff --git a/Tests/t_ldap_controls_ppolicy.py b/Tests/t_ldap_controls_ppolicy.py index 8644e563..d20ee500 100644 --- a/Tests/t_ldap_controls_ppolicy.py +++ b/Tests/t_ldap_controls_ppolicy.py @@ -9,6 +9,7 @@ PP_GRACEAUTH = b'0\x84\x00\x00\x00\t\xa0\x84\x00\x00\x00\x03\x81\x01\x02' PP_TIMEBEFORE = b'0\x84\x00\x00\x00\t\xa0\x84\x00\x00\x00\x03\x80\x012' +PP_ACCOUNT_LOCKOUT = b'0\x03\x81\x01\x01' class TestControlsPPolicy(unittest.TestCase): @@ -28,6 +29,11 @@ def test_ppolicy_timebefore(self): pp.decodeControlValue(PP_TIMEBEFORE) self.assertPPolicy(pp, timeBeforeExpiration=50) + def test_ppolicy_account_lockout(self): + pp = ppolicy.PasswordPolicyControl() + pp.decodeControlValue(PP_ACCOUNT_LOCKOUT) + self.assertPPolicy(pp, error=1) + if __name__ == '__main__': unittest.main() diff --git a/Tests/t_ldapobject.py b/Tests/t_ldapobject.py index 0619d514..2f79cef6 100644 --- a/Tests/t_ldapobject.py +++ b/Tests/t_ldapobject.py @@ -28,9 +28,10 @@ os.environ['LDAPNOINIT'] = '1' import ldap +import ldap.controls +import ldap.controls.ppolicy from ldap.ldapobject import SimpleLDAPObject, ReconnectLDAPObject - -from slapdtest import SlapdTestCase +from slapdtest import SlapdTestCase, PPolicyEnabledSlapdTestCase from slapdtest import requires_ldapi, requires_sasl, requires_tls @@ -75,6 +76,72 @@ """ +class Test02_ResponseControl(PPolicyEnabledSlapdTestCase): + """ + tests abount response controls sent by the server + """ + + ldap_object_class = SimpleLDAPObject + + @classmethod + def setUpClass(cls): + super(Test02_ResponseControl, cls).setUpClass() + # insert some Foo* objects via ldapadd + cls.server.ldapadd( + LDIF_TEMPLATE % { + '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:], + } + ) + + # Very strict pwdMaxFailure in order to easily test the cases where + # bind failure with response controls is needed + cls.server.ldapadd( + '''dn: {dn} +objectClass: organizationalRole +objectClass: pwdPolicy +cn: default-ppolicy +pwdAttribute: userPassword +pwdLockout: TRUE +pwdMaxFailure: 1 +pwdLockoutDuration: 60 +pwdFailureCountInterval: 3600'''.format(dn=cls.server.default_ppolicy_dn) + ) + + def test_response_controls_are_attached_to_exceptions(self): + base = self.server.suffix + cn = "test_response_controls_are_attached_to_exceptions" + user_dn = "cn={},{}".format(cn, base) + password = "user5_pw" + + self.server.ldapadd( + '''dn: {dn} +objectClass: applicationProcess +objectClass: simpleSecurityObject +cn: {cn} +userPassword: {password}'''.format(cn=cn, dn=user_dn, password=password) + ) + + ldap_conn = self._make_ldap_object(bytes_mode=False) + + # Firstly cause a bind failure to lock out the account + with self.assertRaises(ldap.INVALID_CREDENTIALS): + wrong_password = 'wrong' + password + ldap_conn.simple_bind_s(user_dn, wrong_password) + + with self.assertRaises(ldap.INVALID_CREDENTIALS) as cm: + ldap_conn.simple_bind_s( + user_dn, password, + serverctrls=[ldap.controls.ppolicy.PasswordPolicyControl()]) + + controls = cm.exception.args[0]['ctrls'] + pp = ldap.controls.DecodeControlTuples(controls)[0] + self.assertEqual(pp.error, 1) # error == 1 means AccountLockout + + class Test00_SimpleLDAPObject(SlapdTestCase): """ test LDAP search operations From c76f08792cf74cd5a4f7b274e70de274441984dc Mon Sep 17 00:00:00 2001 From: SOMA Yuki Date: Wed, 21 Nov 2018 15:04:06 +0900 Subject: [PATCH 2/9] remove PPolicyEnabledSlapdTestCase --- Lib/slapdtest/__init__.py | 2 +- Lib/slapdtest/_slapdtest.py | 9 --------- Tests/t_ldapobject.py | 5 +++-- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/Lib/slapdtest/__init__.py b/Lib/slapdtest/__init__.py index 567e666b..bf8dad03 100644 --- a/Lib/slapdtest/__init__.py +++ b/Lib/slapdtest/__init__.py @@ -9,7 +9,7 @@ from slapdtest._slapdtest import ( SlapdObject, SlapdTestCase, - PPolicyEnabledSlapdObject, PPolicyEnabledSlapdTestCase, + PPolicyEnabledSlapdObject, SysLogHandler) from slapdtest._slapdtest import requires_ldapi, requires_sasl, requires_tls from slapdtest._slapdtest import skip_unless_ci diff --git a/Lib/slapdtest/_slapdtest.py b/Lib/slapdtest/_slapdtest.py index 93e9d0a2..3a820b0f 100644 --- a/Lib/slapdtest/_slapdtest.py +++ b/Lib/slapdtest/_slapdtest.py @@ -654,12 +654,3 @@ class PPolicyEnabledSlapdObject(SlapdObject): 'ppolicy_use_lockout']) }, ) - - -class PPolicyEnabledSlapdTestCase(SlapdTestCase): - """ - A subclass of :py:class:`SlapdTestCase`, which uses - :py:class:`PPolicyEnabledSlapdObject` as the slapd controller. - """ - - server_class = PPolicyEnabledSlapdObject diff --git a/Tests/t_ldapobject.py b/Tests/t_ldapobject.py index 2f79cef6..5633866a 100644 --- a/Tests/t_ldapobject.py +++ b/Tests/t_ldapobject.py @@ -31,7 +31,7 @@ import ldap.controls import ldap.controls.ppolicy from ldap.ldapobject import SimpleLDAPObject, ReconnectLDAPObject -from slapdtest import SlapdTestCase, PPolicyEnabledSlapdTestCase +from slapdtest import SlapdTestCase, PPolicyEnabledSlapdObject from slapdtest import requires_ldapi, requires_sasl, requires_tls @@ -76,12 +76,13 @@ """ -class Test02_ResponseControl(PPolicyEnabledSlapdTestCase): +class Test02_ResponseControl(SlapdTestCase): """ tests abount response controls sent by the server """ ldap_object_class = SimpleLDAPObject + server_class = PPolicyEnabledSlapdObject @classmethod def setUpClass(cls): From cc7ef3b45ad087128db19dc0031467d56844b15b Mon Sep 17 00:00:00 2001 From: SOMA Yuki Date: Wed, 21 Nov 2018 15:17:21 +0900 Subject: [PATCH 3/9] avoid to export PPolicyEnabledSlapdObject --- Lib/slapdtest/__init__.py | 5 +---- Lib/slapdtest/_slapdtest.py | 31 ------------------------------- Tests/t_ldapobject.py | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 33 insertions(+), 36 deletions(-) diff --git a/Lib/slapdtest/__init__.py b/Lib/slapdtest/__init__.py index bf8dad03..56ba2c91 100644 --- a/Lib/slapdtest/__init__.py +++ b/Lib/slapdtest/__init__.py @@ -7,9 +7,6 @@ __version__ = '3.1.0' -from slapdtest._slapdtest import ( - SlapdObject, SlapdTestCase, - PPolicyEnabledSlapdObject, - SysLogHandler) +from slapdtest._slapdtest import SlapdObject, SlapdTestCase, SysLogHandler from slapdtest._slapdtest import requires_ldapi, requires_sasl, requires_tls from slapdtest._slapdtest import skip_unless_ci diff --git a/Lib/slapdtest/_slapdtest.py b/Lib/slapdtest/_slapdtest.py index 3a820b0f..b0f1042e 100644 --- a/Lib/slapdtest/_slapdtest.py +++ b/Lib/slapdtest/_slapdtest.py @@ -623,34 +623,3 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): cls.server.stop() - - -class PPolicyEnabledSlapdObject(SlapdObject): - """ - A subclass of :py:class:`SlapdObject` with password policy enabled. - Note that this class has no actual password policy configuration entries. - It is the job of the users of this class to define - the default password policies on their own. - The dn of the default is :attr:`.default_ppolicy_dn` of this class. - """ - - openldap_schema_files = ( - 'core.schema', 'ppolicy.schema' - ) - modules = ( - 'ppolicy', - ) - - default_ppolicy_dn = "cn=default-ppolicy,%(suffix)s" % { - 'suffix': SlapdObject.suffix - } - - overlays = ( - { - 'name': 'ppolicy', - 'configuration': "\n".join([ - 'ppolicy_default "{}"'.format(default_ppolicy_dn), - # let slapd tell the clients that they are locked out - 'ppolicy_use_lockout']) - }, - ) diff --git a/Tests/t_ldapobject.py b/Tests/t_ldapobject.py index 5633866a..9f503f87 100644 --- a/Tests/t_ldapobject.py +++ b/Tests/t_ldapobject.py @@ -31,7 +31,7 @@ import ldap.controls import ldap.controls.ppolicy from ldap.ldapobject import SimpleLDAPObject, ReconnectLDAPObject -from slapdtest import SlapdTestCase, PPolicyEnabledSlapdObject +from slapdtest import SlapdTestCase, SlapdObject from slapdtest import requires_ldapi, requires_sasl, requires_tls @@ -76,6 +76,37 @@ """ +class PPolicyEnabledSlapdObject(SlapdObject): + """ + A subclass of :py:class:`SlapdObject` with password policy enabled. + Note that this class has no actual password policy configuration entries. + It is the job of the users of this class to define + the default password policies on their own. + The dn of the default is :attr:`.default_ppolicy_dn` of this class. + """ + + openldap_schema_files = ( + 'core.schema', 'ppolicy.schema' + ) + modules = ( + 'ppolicy', + ) + + default_ppolicy_dn = "cn=default-ppolicy,%(suffix)s" % { + 'suffix': SlapdObject.suffix + } + + overlays = ( + { + 'name': 'ppolicy', + 'configuration': "\n".join([ + 'ppolicy_default "{}"'.format(default_ppolicy_dn), + # let slapd tell the clients that they are locked out + 'ppolicy_use_lockout']) + }, + ) + + class Test02_ResponseControl(SlapdTestCase): """ tests abount response controls sent by the server From 0144bdb17f82695989507b8e34f80f588fa5ce11 Mon Sep 17 00:00:00 2001 From: SOMA Yuki Date: Wed, 21 Nov 2018 15:18:04 +0900 Subject: [PATCH 4/9] trim a redundant comment --- Modules/constants.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/constants.c b/Modules/constants.c index bcd5dff2..5f8fc321 100644 --- a/Modules/constants.c +++ b/Modules/constants.c @@ -106,7 +106,6 @@ LDAPraise_exception(LDAP *l, char *msg, PyObject *pyctrls) if (pyctrls != NULL) { PyDict_SetItemString(info, "ctrls", pyctrls); - /* Py_XDECREF(pyctrls) must be called on caller side */ } if (errnum == LDAP_REFERRAL) { From a0ba3993602892956ea68a690c526c4498250b0a Mon Sep 17 00:00:00 2001 From: SOMA Yuki Date: Wed, 21 Nov 2018 15:20:55 +0900 Subject: [PATCH 5/9] Test: assert len(ctrls) & remove a magic number --- Tests/t_ldapobject.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Tests/t_ldapobject.py b/Tests/t_ldapobject.py index 9f503f87..879fcee0 100644 --- a/Tests/t_ldapobject.py +++ b/Tests/t_ldapobject.py @@ -170,8 +170,11 @@ def test_response_controls_are_attached_to_exceptions(self): serverctrls=[ldap.controls.ppolicy.PasswordPolicyControl()]) controls = cm.exception.args[0]['ctrls'] - pp = ldap.controls.DecodeControlTuples(controls)[0] - self.assertEqual(pp.error, 1) # error == 1 means AccountLockout + decoded_controls = ldap.controls.DecodeControlTuples(controls) + self.assertEqual(len(decoded_controls), 1) + pp = decoded_controls[0] + expected_error = ldap.controls.ppolicy.PasswordPolicyError('accountLocked') + self.assertEqual(pp.error, int(expected_error)) class Test00_SimpleLDAPObject(SlapdTestCase): From 2b5d1eeca5acc5c4f6e1f13d969ec84ce5d82bef Mon Sep 17 00:00:00 2001 From: SOMA Yuki Date: Wed, 21 Nov 2018 16:56:55 +0900 Subject: [PATCH 6/9] Doc: delete about slapdtest.PPolicyEnabled... --- Doc/reference/slapdtest.rst | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Doc/reference/slapdtest.rst b/Doc/reference/slapdtest.rst index 824c5dd9..90c671ad 100644 --- a/Doc/reference/slapdtest.rst +++ b/Doc/reference/slapdtest.rst @@ -27,8 +27,3 @@ Classes .. autoclass:: slapdtest.SlapdTestCase :members: -.. autoclass:: slapdtest.PPolicyEnabledSlapdObject - :members: - -.. autoclass:: slapdtest.PPolicyEnabledSlapdTestCase - :members: From a616cae85e6985989ed4b2c86d4392941de3bb1a Mon Sep 17 00:00:00 2001 From: SOMA Yuki Date: Wed, 21 Nov 2018 17:25:32 +0900 Subject: [PATCH 7/9] Doc: slapdtest: modules and overlay attributes --- Lib/slapdtest/_slapdtest.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Lib/slapdtest/_slapdtest.py b/Lib/slapdtest/_slapdtest.py index b0f1042e..a9aa8f44 100644 --- a/Lib/slapdtest/_slapdtest.py +++ b/Lib/slapdtest/_slapdtest.py @@ -191,7 +191,17 @@ class SlapdObject(object): 'core.schema', ) + #: List (or tuple) of OpenLDAP module names you want to activate. + #: Default is empty. modules = () + + #: List (or tuple) of OpenLDAP overlay settings you want to include. + #: Default is empty. + #: Each element is a dict of the form of:: + #: + #: {"name": overlay_name, + #: "configuration": configuration_text} + #: overlays = () TMPDIR = os.environ.get('TMP', os.getcwd()) From e8648f239b55e19785be823a220ea223c1c620bd Mon Sep 17 00:00:00 2001 From: SOMA Yuki Date: Wed, 21 Nov 2018 18:17:06 +0900 Subject: [PATCH 8/9] delete _make_ldap_object() --- Lib/slapdtest/_slapdtest.py | 11 ++--------- Tests/t_ldapobject.py | 2 +- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/Lib/slapdtest/_slapdtest.py b/Lib/slapdtest/_slapdtest.py index a9aa8f44..5b566c35 100644 --- a/Lib/slapdtest/_slapdtest.py +++ b/Lib/slapdtest/_slapdtest.py @@ -612,17 +612,10 @@ def _open_ldap_conn(self, who=None, cred=None, **kwargs): """ return a LDAPObject instance after simple bind """ - ldap_conn = self._make_ldap_object(**kwargs) - ldap_conn.simple_bind_s(who or self.server.root_dn, cred or self.server.root_pw) - return ldap_conn - - def _make_ldap_object(self, **kwargs): - """ - return an unbound LDAPObject instance with common ldap options. - """ ldap_conn = self.ldap_object_class(self.server.ldap_uri, **kwargs) ldap_conn.protocol_version = 3 - # ldap_conn.set_option(ldap.OPT_REFERRALS, 0) + #ldap_conn.set_option(ldap.OPT_REFERRALS, 0) + ldap_conn.simple_bind_s(who or self.server.root_dn, cred or self.server.root_pw) return ldap_conn @classmethod diff --git a/Tests/t_ldapobject.py b/Tests/t_ldapobject.py index 879fcee0..2a023642 100644 --- a/Tests/t_ldapobject.py +++ b/Tests/t_ldapobject.py @@ -157,7 +157,7 @@ def test_response_controls_are_attached_to_exceptions(self): userPassword: {password}'''.format(cn=cn, dn=user_dn, password=password) ) - ldap_conn = self._make_ldap_object(bytes_mode=False) + ldap_conn = self.ldap_object_class(self.server.ldap_uri) # Firstly cause a bind failure to lock out the account with self.assertRaises(ldap.INVALID_CREDENTIALS): From 9ed502d34c801ef258cf52032971a76cda1473f1 Mon Sep 17 00:00:00 2001 From: SOMA Yuki Date: Wed, 21 Nov 2018 18:32:44 +0900 Subject: [PATCH 9/9] Test: check also empty control list --- Tests/t_ldapobject.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Tests/t_ldapobject.py b/Tests/t_ldapobject.py index 2a023642..90392258 100644 --- a/Tests/t_ldapobject.py +++ b/Tests/t_ldapobject.py @@ -160,10 +160,13 @@ def test_response_controls_are_attached_to_exceptions(self): ldap_conn = self.ldap_object_class(self.server.ldap_uri) # Firstly cause a bind failure to lock out the account - with self.assertRaises(ldap.INVALID_CREDENTIALS): + with self.assertRaises(ldap.INVALID_CREDENTIALS) as cm: wrong_password = 'wrong' + password ldap_conn.simple_bind_s(user_dn, wrong_password) + empty_controls = cm.exception.args[0]['ctrls'] + self.assertEqual(len(empty_controls), 0) + with self.assertRaises(ldap.INVALID_CREDENTIALS) as cm: ldap_conn.simple_bind_s( user_dn, password, pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy