From 1a97ca1a6f77cabca78d18bfd8a9f46939f11f8a Mon Sep 17 00:00:00 2001
From: Reto Kupferschmid <kupferschmid@puzzle.ch>
Date: Fri, 4 Nov 2022 07:07:06 +0100
Subject: [PATCH] ldap_attrs: escape ldap search filter (#5435)

* escape ldap search filter

* move escape to separate line

* add changelog fragment

* Update changelogs/fragments/5435-escape-ldap-param.yml

Co-authored-by: Felix Fontein <felix@fontein.de>

* fix encoding

* fixup! fix encoding

Co-authored-by: Felix Fontein <felix@fontein.de>
---
 changelogs/fragments/5435-escape-ldap-param.yml | 2 ++
 plugins/modules/ldap_attrs.py                   | 6 ++++--
 2 files changed, 6 insertions(+), 2 deletions(-)
 create mode 100644 changelogs/fragments/5435-escape-ldap-param.yml

diff --git a/changelogs/fragments/5435-escape-ldap-param.yml b/changelogs/fragments/5435-escape-ldap-param.yml
new file mode 100644
index 0000000000..3f22f61759
--- /dev/null
+++ b/changelogs/fragments/5435-escape-ldap-param.yml
@@ -0,0 +1,2 @@
+bugfixes:
+  - ldap_attrs - fix bug which caused a ``Bad search filter`` error. The error was occuring when the ldap attribute value contained special characters such as ``(`` or ``*`` (https://github.com/ansible-collections/community.general/issues/5434, https://github.com/ansible-collections/community.general/pull/5435).
diff --git a/plugins/modules/ldap_attrs.py b/plugins/modules/ldap_attrs.py
index 97275c45d5..61ae291956 100644
--- a/plugins/modules/ldap_attrs.py
+++ b/plugins/modules/ldap_attrs.py
@@ -168,7 +168,7 @@ modlist:
 import traceback
 
 from ansible.module_utils.basic import AnsibleModule, missing_required_lib
-from ansible.module_utils.common.text.converters import to_native, to_bytes
+from ansible.module_utils.common.text.converters import to_native, to_bytes, to_text
 from ansible_collections.community.general.plugins.module_utils.ldap import LdapGeneric, gen_specs
 
 import re
@@ -176,6 +176,7 @@ import re
 LDAP_IMP_ERR = None
 try:
     import ldap
+    import ldap.filter
 
     HAS_LDAP = True
 except ImportError:
@@ -264,7 +265,8 @@ class LdapAttrs(LdapGeneric):
     def _is_value_present(self, name, value):
         """ True if the target attribute has the given value. """
         try:
-            filterstr = "(%s=%s)" % (name, value.decode())
+            escaped_value = ldap.filter.escape_filter_chars(to_text(value))
+            filterstr = "(%s=%s)" % (name, escaped_value)
             dns = self.connection.search_s(self.dn, ldap.SCOPE_BASE, filterstr)
             is_present = len(dns) == 1
         except ldap.NO_SUCH_OBJECT: