# HG changeset patch # User Julien Tayon # Date 1582669378 -3600 # Node ID 5a9d1e64f505551d27f64500f465a4a48bceeac2 # Parent ba528f08ddfa57e09328a4c96da19e0c82a8ff85 [ldapfeed] make code compatible with ldap3>=2 * Some constants have been renamed. * Directly bind when data-cnx-dn/data-cnx-password are provided, some servers, including ours require this. * Use raise_exceptions=True to avoid ignored ldap errors * raise in case of failed anonymous bind * do not search for "dn" attribute because this raise an "invalid attribute" with new ldap3 versions * Password is now returned as bytes, so no longer need to encode them before crypt. * modification_date is now returned as a datetime object Co-Authored-By: Philippe Pepiot Closes #16073071 diff -r ba528f08ddfa -r 5a9d1e64f505 cubicweb/server/sources/ldapfeed.py --- a/cubicweb/server/sources/ldapfeed.py Tue Feb 25 22:45:42 2020 +0100 +++ b/cubicweb/server/sources/ldapfeed.py Tue Feb 25 23:22:58 2020 +0100 @@ -17,8 +17,6 @@ # with CubicWeb. If not, see . """cubicweb ldap feed source""" -from datetime import datetime - import ldap3 from logilab.common.configuration import merge_options @@ -30,10 +28,11 @@ from cubicweb import _ # search scopes -LDAP_SCOPES = {'BASE': ldap3.SEARCH_SCOPE_BASE_OBJECT, - 'ONELEVEL': ldap3.SEARCH_SCOPE_SINGLE_LEVEL, - 'SUBTREE': ldap3.SEARCH_SCOPE_WHOLE_SUBTREE} - +LDAP_SCOPES = { + 'BASE': ldap3.BASE, + 'ONELEVEL': ldap3.LEVEL, + 'SUBTREE': ldap3.SUBTREE, +} # map ldap protocol to their standard port PROTO_PORT = {'ldap': 389, @@ -250,7 +249,7 @@ # check password by establishing a (unused) connection try: self._connect(user, password) - except ldap3.LDAPException as ex: + except ldap3.core.exceptions.LDAPException as ex: # Something went wrong, most likely bad credentials self.info('while trying to authenticate %s: %s', user, ex) raise AuthenticationError() @@ -266,18 +265,27 @@ def _connect(self, user=None, userpwd=None): protocol, host, port = self.connection_info() + kwargs = {} + if user: + kwargs['user'] = user['dn'] + elif self.cnx_dn: + kwargs['user'] = self.cnx_dn + if self.cnx_pwd: + kwargs['password'] = self.cnx_pwd self.info('connecting %s://%s:%s as %s', protocol, host, port, - user and user['dn'] or 'anonymous') + kwargs.get('user', 'anonymous')) server = ldap3.Server(host, port=int(port)) conn = ldap3.Connection( - server, user=user and user['dn'], - client_strategy=ldap3.STRATEGY_SYNC_RESTARTABLE, - auto_referrals=False) + server, client_strategy=ldap3.RESTARTABLE, auto_referrals=False, + raise_exceptions=True, + **kwargs) + # Now bind with the credentials given. Let exceptions propagate out. if user is None: - # XXX always use simple bind for data connection + # anonymous bind if not self.cnx_dn: - conn.bind() + if not conn.bind(): + raise AuthenticationError(conn.result["message"]) else: self._authenticate(conn, {'dn': self.cnx_dn}, self.cnx_pwd) else: @@ -288,7 +296,6 @@ return conn def _auth_simple(self, conn, user, userpwd): - conn.authentication = ldap3.AUTH_SIMPLE conn.user = user['dn'] conn.password = userpwd return conn.bind() @@ -313,7 +320,7 @@ if self._conn is None: self._conn = self._connect() ldapcnx = self._conn - if not ldapcnx.search(base, searchstr, search_scope=scope, attributes=attrs): + if not ldapcnx.search(base, searchstr, search_scope=scope, attributes=set(attrs) - {'dn'}): return [] result = [] for rec in ldapcnx.response: @@ -330,13 +337,13 @@ itemdict = {'dn': dn} for key, value in iterator: if self.user_attrs.get(key) == 'upassword': # XXx better password detection - value = value[0].encode('utf-8') + value = value[0] # we only support ldap_salted_sha1 for ldap sources, see: server/utils.py if not value.startswith(b'{SSHA}'): value = utils.crypt_password(value) itemdict[key] = Binary(value) elif self.user_attrs.get(key) == 'modification_date': - itemdict[key] = datetime.strptime(value[0], '%Y%m%d%H%M%SZ') + itemdict[key] = value else: if len(value) == 1: itemdict[key] = value = value[0] diff -r ba528f08ddfa -r 5a9d1e64f505 requirements/test-server.txt --- a/requirements/test-server.txt Tue Feb 25 22:45:42 2020 +0100 +++ b/requirements/test-server.txt Tue Feb 25 23:22:58 2020 +0100 @@ -1,2 +1,2 @@ psycopg2-binary -ldap3 < 2 +ldap3<3,>2