PY3: Ensure LDAP searches use unicode attributes

This is a bug fix that corresponds to changes missed in commit
eca0829c4c.

In Python 3, python-ldap no longer allows bytes for some fields (DNs,
RDNs, attribute names, queries). Instead, text values are represented
as str, the Unicode text type. Compatibility support is provided for
Python 2 by setting bytes_mode=False [1]. This support was provided
in commit eca0829c4c.

In this patch we ensure that attribute names specified in searches
are no longer encoded.

[1] More details about byte/str usage in python-ldap can be found at:
http://www.python-ldap.org/en/latest/bytes_mode.html#bytes-mode

Change-Id: If3398e2d08ea14fa4b8c498b2a9a7c7edb47b9e5
Closes-Bug: #1820333
This commit is contained in:
Corey Bryant 2019-03-18 13:46:37 -04:00
parent f0c2e798f7
commit d6df1dff3e
4 changed files with 31 additions and 15 deletions

View File

@ -26,7 +26,7 @@ import ldappool
from oslo_log import log
from oslo_utils import reflection
import six
from six.moves import map, zip
from six.moves import zip
from six import PY2
from keystone.common import driver_hints
@ -951,13 +951,9 @@ class KeystoneLDAPHandler(LDAPHandler):
ldap_result = self._paged_search_s(base, scope,
filterstr, attrlist)
else:
if attrlist is None:
attrlist_utf8 = None
else:
attrlist_utf8 = list(map(utf8_encode, attrlist))
try:
ldap_result = self.conn.search_s(base, scope, filterstr,
attrlist_utf8, attrsonly)
attrlist, attrsonly)
except ldap.SIZELIMIT_EXCEEDED:
raise exception.LDAPSizeLimitExceeded()
@ -1001,15 +997,10 @@ class KeystoneLDAPHandler(LDAPHandler):
cookie='')
page_ctrl_oid = ldap.controls.SimplePagedResultsControl.controlType
if attrlist is None:
attrlist_utf8 = None
else:
attrlist = [attr for attr in attrlist if attr is not None]
attrlist_utf8 = list(map(utf8_encode, attrlist))
msgid = self.conn.search_ext(base,
scope,
filterstr,
attrlist_utf8,
attrlist,
serverctrls=[lc])
# Endless loop request pages on ldap server until it has no data
while True:
@ -1033,7 +1024,7 @@ class KeystoneLDAPHandler(LDAPHandler):
msgid = self.conn.search_ext(base,
scope,
filterstr,
attrlist_utf8,
attrlist,
serverctrls=[lc])
else:
# Exit condition no more data on server

View File

@ -516,7 +516,7 @@ class FakeLdap(common.LDAPHandler):
raise AssertionError('No objectClass in search filter')
# filter the attributes by attrlist
attrs = {k: v for k, v in attrs.items()
if not attrlist or k in common.utf8_decode(attrlist)}
if not attrlist or k in attrlist}
objects.append((dn, attrs))
return objects

View File

@ -404,7 +404,14 @@ class LDAPPagedResultsTest(unit.TestCase):
conn = PROVIDERS.identity_api.user.get_connection()
conn._paged_search_s('dc=example,dc=test',
ldap.SCOPE_SUBTREE,
'objectclass=*')
'objectclass=*',
['mail', 'userPassword'])
# verify search_ext() args - attrlist is tricky due to ordering
args, _ = mock_search_ext.call_args
self.assertEqual(
('dc=example,dc=test', 2, 'objectclass=*'), args[0:3])
attrlist = sorted([attr for attr in args[3] if attr])
self.assertEqual(['mail', 'userPassword'], attrlist)
class CommonLdapTestCase(unit.BaseTestCase):

View File

@ -0,0 +1,18 @@
---
fixes:
- |
[`bug 1798184 <https://bugs.launchpad.net/keystone/+bug/1798184>`_]
[`bug 1820333 <https://bugs.launchpad.net/keystone/+bug/1820333>`_]
In Python 3, python-ldap no longer allows bytes for some fields (DNs,
RDNs, attribute names, queries). Instead, text values are represented
as str, the Unicode text type. Compatibility support is provided for
Python 2 by setting bytes_mode=False [1].
The keystone LDAP backend is updated to adhere to this behavior by using
bytes_mode=False for Python 2 and dropping UTF-8 encoding and decoding
fields that are now represented as text in python-ldap.
[1] More details about byte/str usage in python-ldap can be found at:
http://www.python-ldap.org/en/latest/bytes_mode.html#bytes-mode
Note that at a minimum python-ldappool 2.3.1 is required.