diff options
Diffstat (limited to 'keystone/identity/backends/ldap/common.py')
-rw-r--r-- | keystone/identity/backends/ldap/common.py | 44 |
1 files changed, 34 insertions, 10 deletions
diff --git a/keystone/identity/backends/ldap/common.py b/keystone/identity/backends/ldap/common.py index b9becea74..f2f36718f 100644 --- a/keystone/identity/backends/ldap/common.py +++ b/keystone/identity/backends/ldap/common.py @@ -18,6 +18,7 @@ import functools import os.path import re import sys +import uuid import weakref import ldap.controls @@ -95,7 +96,16 @@ def utf8_decode(value): :raises UnicodeDecodeError: for invalid UTF-8 encoding """ if isinstance(value, six.binary_type): - return _utf8_decoder(value)[0] + try: + return _utf8_decoder(value)[0] + except UnicodeDecodeError: + # NOTE(lbragstad): We could be dealing with a UUID in byte form, + # which some LDAP implementations use. + uuid_byte_string_length = 16 + if len(value) == uuid_byte_string_length: + return six.text_type(uuid.UUID(bytes_le=value)) + else: + raise return six.text_type(value) @@ -1781,6 +1791,7 @@ class EnabledEmuMixIn(BaseLdap): DEFAULT_GROUP_OBJECTCLASS = 'groupOfNames' DEFAULT_MEMBER_ATTRIBUTE = 'member' + DEFAULT_GROUP_MEMBERS_ARE_IDS = False def __init__(self, conf): super(EnabledEmuMixIn, self).__init__(conf) @@ -1797,9 +1808,11 @@ class EnabledEmuMixIn(BaseLdap): if not self.use_group_config: self.member_attribute = self.DEFAULT_MEMBER_ATTRIBUTE self.group_objectclass = self.DEFAULT_GROUP_OBJECTCLASS + self.group_members_are_ids = self.DEFAULT_GROUP_MEMBERS_ARE_IDS else: self.member_attribute = conf.ldap.group_member_attribute self.group_objectclass = conf.ldap.group_objectclass + self.group_members_are_ids = conf.ldap.group_members_are_ids if not self.enabled_emulation_dn: naming_attr_name = 'cn' @@ -1815,10 +1828,19 @@ class EnabledEmuMixIn(BaseLdap): naming_rdn[1]) self.enabled_emulation_naming_attr = naming_attr - def _get_enabled(self, object_id, conn): - dn = self._id_to_dn(object_id) + def _id_to_member_attribute_value(self, object_id): + """Convert id to value expected by member_attribute.""" + if self.group_members_are_ids: + return object_id + return self._id_to_dn(object_id) + + def _is_id_enabled(self, object_id, conn): + member_attr_val = self._id_to_member_attribute_value(object_id) + return self._is_member_enabled(member_attr_val, conn) + + def _is_member_enabled(self, member_attr_val, conn): query = '(%s=%s)' % (self.member_attribute, - ldap.filter.escape_filter_chars(dn)) + ldap.filter.escape_filter_chars(member_attr_val)) try: enabled_value = conn.search_s(self.enabled_emulation_dn, ldap.SCOPE_BASE, @@ -1829,24 +1851,26 @@ class EnabledEmuMixIn(BaseLdap): return bool(enabled_value) def _add_enabled(self, object_id): + member_attr_val = self._id_to_member_attribute_value(object_id) with self.get_connection() as conn: - if not self._get_enabled(object_id, conn): + if not self._is_member_enabled(member_attr_val, conn): modlist = [(ldap.MOD_ADD, self.member_attribute, - [self._id_to_dn(object_id)])] + [member_attr_val])] try: conn.modify_s(self.enabled_emulation_dn, modlist) except ldap.NO_SUCH_OBJECT: attr_list = [('objectClass', [self.group_objectclass]), (self.member_attribute, - [self._id_to_dn(object_id)]), + [member_attr_val]), self.enabled_emulation_naming_attr] conn.add_s(self.enabled_emulation_dn, attr_list) def _remove_enabled(self, object_id): + member_attr_val = self._id_to_member_attribute_value(object_id) modlist = [(ldap.MOD_DELETE, self.member_attribute, - [self._id_to_dn(object_id)])] + [member_attr_val])] with self.get_connection() as conn: try: conn.modify_s(self.enabled_emulation_dn, modlist) @@ -1871,7 +1895,7 @@ class EnabledEmuMixIn(BaseLdap): ref = super(EnabledEmuMixIn, self).get(object_id, ldap_filter) if ('enabled' not in self.attribute_ignore and self.enabled_emulation): - ref['enabled'] = self._get_enabled(object_id, conn) + ref['enabled'] = self._is_id_enabled(object_id, conn) return ref def get_all(self, ldap_filter=None, hints=None): @@ -1883,7 +1907,7 @@ class EnabledEmuMixIn(BaseLdap): if x[0] != self.enabled_emulation_dn] with self.get_connection() as conn: for obj_ref in obj_list: - obj_ref['enabled'] = self._get_enabled( + obj_ref['enabled'] = self._is_id_enabled( obj_ref['id'], conn) return obj_list else: |