From 60303782e5d246e96a485757738509ecbb980458 Mon Sep 17 00:00:00 2001 From: Friedrich Weber Date: Tue, 5 Sep 2017 18:58:14 +0200 Subject: [PATCH] Add an option to ignore SEARCH result references Working on #32 --- deploy/ubuntu-config/proxy.ini | 5 +++++ example-proxy.ini | 5 +++++ pi_ldapproxy/config.py | 1 + pi_ldapproxy/proxy.py | 8 +++++++ pi_ldapproxy/test/test_proxy_simple.py | 31 ++++++++++++++++++++++++++ 5 files changed, 50 insertions(+) diff --git a/deploy/ubuntu-config/proxy.ini b/deploy/ubuntu-config/proxy.ini index 2638197..1371849 100644 --- a/deploy/ubuntu-config/proxy.ini +++ b/deploy/ubuntu-config/proxy.ini @@ -53,6 +53,11 @@ bind-service-account = false # If `bind-service-account` is set to false, but `allow-search` is set to true, only the DNs # in `passthrough-binds` will be able to issue search requests. allow-search = false +# Currently, ldaptor does not support result references which will break +# some apps in combination with AD. This option provides a workaround: +# If it is set to `true`, the LDAP proxy ignores all LDAP SEARCH result references. +# However, this means that the app does not receive any LDAP SEARCH references. +ignore-search-result-references = false [user-mapping] # This setting determines the strategy the LDAP proxy uses to determine the username that is sent to privacyIDEA diff --git a/example-proxy.ini b/example-proxy.ini index 2638197..1371849 100644 --- a/example-proxy.ini +++ b/example-proxy.ini @@ -53,6 +53,11 @@ bind-service-account = false # If `bind-service-account` is set to false, but `allow-search` is set to true, only the DNs # in `passthrough-binds` will be able to issue search requests. allow-search = false +# Currently, ldaptor does not support result references which will break +# some apps in combination with AD. This option provides a workaround: +# If it is set to `true`, the LDAP proxy ignores all LDAP SEARCH result references. +# However, this means that the app does not receive any LDAP SEARCH references. +ignore-search-result-references = false [user-mapping] # This setting determines the strategy the LDAP proxy uses to determine the username that is sent to privacyIDEA diff --git a/pi_ldapproxy/config.py b/pi_ldapproxy/config.py index b8bbff3..ea17fac 100644 --- a/pi_ldapproxy/config.py +++ b/pi_ldapproxy/config.py @@ -20,6 +20,7 @@ passthrough-binds = force_list bind-service-account = boolean(default=False) allow-search = boolean(default=False) +ignore-search-result-references = boolean(default=False) [service-account] dn = string diff --git a/pi_ldapproxy/proxy.py b/pi_ldapproxy/proxy.py index 2a534ec..a23bf6e 100644 --- a/pi_ldapproxy/proxy.py +++ b/pi_ldapproxy/proxy.py @@ -204,6 +204,13 @@ def handleProxiedResponse(self, response, request, controls): # reset counter and storage self.search_response_entries = 0 self.last_search_response_entry = None + elif isinstance(response, pureldap.LDAPSearchResultReference): + if self.factory.ignore_search_result_references: + log.info('Ignoring LDAP SEARCH result reference ...') + return None + else: + log.warn('Possibly sending an invalid LDAP SEARCH result reference, ' + 'check the ignore-search-result-reference config option for more details.') except Exception, e: log.failure("Unhandled error in handleProxiedResponse: {e}", e=e) raise @@ -308,6 +315,7 @@ def __init__(self, config): self.allow_search = config['ldap-proxy']['allow-search'] self.bind_service_account = config['ldap-proxy']['bind-service-account'] + self.ignore_search_result_references = config['ldap-proxy']['ignore-search-result-references'] user_mapping_strategy = USER_MAPPING_STRATEGIES[config['user-mapping']['strategy']] log.info('Using user mapping strategy: {strategy!r}', strategy=user_mapping_strategy) diff --git a/pi_ldapproxy/test/test_proxy_simple.py b/pi_ldapproxy/test/test_proxy_simple.py index 0b9c057..a2d495c 100644 --- a/pi_ldapproxy/test/test_proxy_simple.py +++ b/pi_ldapproxy/test/test_proxy_simple.py @@ -71,3 +71,34 @@ def test_passthrough_account_search_fails(self): entry = LDAPEntry(client, 'cn=users,dc=test,dc=local') d = entry.search('(objectClass=*)', scope=pureldap.LDAP_SCOPE_wholeSubtree) yield self.assertFailure(d, ldaperrors.LDAPInsufficientAccessRights) + +class TestProxyIgnoringReferences(ProxyTestCase): + privacyidea_credentials = { + 'hugo@default': 'secret' + } + additional_config = { + 'ldap-proxy': { + 'ignore-search-result-references': True, + 'allow-search': True, + } + } + + @defer.inlineCallbacks + def test_ignores_search_result_reference(self): + dn = 'uid=hugo,cn=users,dc=test,dc=local' + server, client = self.create_server_and_client( + [ + pureldap.LDAPBindResponse(resultCode=0) + ], + [ + pureldap.LDAPSearchResultEntry(dn, [('someattr', ['somevalue'])]), + pureldap.LDAPSearchResultReference(), # NOTE: ldaptor does not really support these + pureldap.LDAPSearchResultReference(), + pureldap.LDAPSearchResultDone(ldaperrors.Success.resultCode), + ] + ) + yield client.bind('uid=passthrough,cn=users,dc=test,dc=local', 'some-secret') + entry = LDAPEntry(client, 'cn=users,dc=test,dc=local') + r = yield entry.search('(objectClass=*)', scope=pureldap.LDAP_SCOPE_wholeSubtree) + self.assertEqual(len(r), 1) + self.assertEqual(r[0].dn, dn)