Skip to content

Commit 473371e

Browse files
authored
Merge pull request #287 from adorton-adobe/feature/ldap-escape-string
Escape LDAP special chars.
2 parents a2a9ee7 + 49d9588 commit 473371e

File tree

1 file changed

+31
-2
lines changed

1 file changed

+31
-2
lines changed

user_sync/connector/directory_ldap.py

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ def load_users_and_groups(self, groups, extended_attributes, all_users):
133133
if not group_dn:
134134
self.logger.warning("No group found for: %s", group)
135135
continue
136-
group_member_subfilter = group_member_filter_format.format(group_dn=group_dn)
136+
group_member_subfilter = self.format_ldap_query_string(group_member_filter_format, group_dn=group_dn)
137137
if not group_member_subfilter.startswith('('):
138138
group_member_subfilter = six.text_type('(') + group_member_subfilter + six.text_type(')')
139139
user_subfilter = all_users_filter
@@ -178,8 +178,9 @@ def find_ldap_group_dn(self, group):
178178
base_dn = six.text_type(options['base_dn'])
179179
group_filter_format = six.text_type(options['group_filter_format'])
180180
try:
181+
filter_string = self.format_ldap_query_string(group_filter_format, group=group)
181182
res = connection.search_s(base_dn, ldap.SCOPE_SUBTREE,
182-
filterstr=group_filter_format.format(group=group), attrsonly=1)
183+
filterstr=filter_string, attrsonly=1)
183184
except Exception as e:
184185
raise AssertionException('Unexpected LDAP failure reading group info: %s' % e)
185186
group_dn = None
@@ -324,6 +325,34 @@ def iter_search_result(self, base_dn, scope, filter_string, attributes):
324325
connection.abandon(msgid)
325326
raise
326327

328+
@staticmethod
329+
def format_ldap_query_string(query, **kwargs):
330+
"""
331+
Escape LDAP special characters that may appear in injected query strings
332+
Should be used with any string that will be injected into an LDAP query.
333+
:param query:
334+
:param kwargs:
335+
:return:
336+
"""
337+
# See http://www.rfc-editor.org/rfc/rfc4515.txt
338+
escape_chars = six.text_type('*()\\&|<>~!:')
339+
escaped_args = {}
340+
# kwargs is a dict that would normally be passed to string.format
341+
for k, v in six.iteritems(kwargs):
342+
# LDAP special characters are escaped in the general format '\' + hex(char)
343+
# we need to run through the string char by char and if the char exists in
344+
# the escape_char list, get the ord of it (decimal ascii value), convert it to hex, and
345+
# replace the '0x' with '\'
346+
escaped_list = []
347+
for c in v:
348+
if c in escape_chars:
349+
replace = six.text_type(hex(ord(c))).replace('0x', '\\')
350+
escaped_list.append(replace)
351+
else:
352+
escaped_list.append(c)
353+
escaped_args[k] = six.text_type('').join(escaped_list)
354+
return query.format(**escaped_args)
355+
327356

328357
class LDAPValueFormatter(object):
329358
encoding = 'utf8'

0 commit comments

Comments
 (0)