From e8586e954e42195d10d41166a69991caa903d870 Mon Sep 17 00:00:00 2001 From: Marco Huenseler Date: Fri, 4 Aug 2017 18:12:38 +0200 Subject: Fix #2: Import escape_attribute_value from upstream --- radicale_auth_ldap/__init__.py | 7 ++- radicale_auth_ldap/ldap3imports.py | 97 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 radicale_auth_ldap/ldap3imports.py diff --git a/radicale_auth_ldap/__init__.py b/radicale_auth_ldap/__init__.py index d04c43b..5ef2b13 100644 --- a/radicale_auth_ldap/__init__.py +++ b/radicale_auth_ldap/__init__.py @@ -25,12 +25,15 @@ Authentication based on the ``ldap3`` module (https://github.com/cannatag/ldap3/). """ + import ldap3 import ldap3.core.exceptions -import ldap3.utils.dn from radicale.auth import BaseAuth +import radicale_auth_ldap.ldap3imports + + class Auth(BaseAuth): def is_authenticated(self, user, password): """Check if ``user``/``password`` couple is valid.""" @@ -53,7 +56,7 @@ class Auth(BaseAuth): except Exception as err: self.logger.debug("LDAP error: %s" % err) - distinguished_name = "%s=%s" % (ATTRIBUTE, ldap3.utils.dn.escape_attribute_value(user)) + distinguished_name = "%s=%s" % (ATTRIBUTE, ldap3imports.escape_attribute_value(user)) self.logger.debug("LDAP bind for %s in base %s" % (distinguished_name, BASE)) if FILTER: diff --git a/radicale_auth_ldap/ldap3imports.py b/radicale_auth_ldap/ldap3imports.py new file mode 100644 index 0000000..840ff21 --- /dev/null +++ b/radicale_auth_ldap/ldap3imports.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- + +""" +This code was imported from ldap3, because upstream obviously deprecated this. +Until I come around finding a better solution, this will stay here. +All this code was written by people from the ldap3 project and keeps the original license, of course. + +Original header below: + +# Created on 2014.09.08 +# +# Author: Giovanni Cannata +# +# Copyright 2014, 2015, 2016 Giovanni Cannata +# +# This file is part of ldap3. +# +# ldap3 is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# ldap3 is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with ldap3 in the COPYING and COPYING.LESSER files. +# If not, see . +""" +from string import hexdigits + +STATE_ANY = 0 +STATE_ESCAPE = 1 +STATE_ESCAPE_HEX = 2 + + +def escape_attribute_value(attribute_value): + if not attribute_value: + return '' + + if attribute_value[0] == '#': # with leading SHARP only pairs of hex characters are valid + valid_hex = True + if len(attribute_value) % 2 == 0: # string must be # + HEX HEX (an odd number of chars) + valid_hex = False + + if valid_hex: + for c in attribute_value: + if c not in hexdigits: # allowed only hex digits as per RFC 4514 + valid_hex = False + break + + if valid_hex: + return attribute_value + + state = STATE_ANY + escaped = '' + tmp_buffer = '' + for c in attribute_value: + if state == STATE_ANY: + if c == '\\': + state = STATE_ESCAPE + elif c in '"#+,;<=>\00': + escaped += '\\' + c + else: + escaped += c + elif state == STATE_ESCAPE: + if c in hexdigits: + tmp_buffer = c + state = STATE_ESCAPE_HEX + elif c in ' "#+,;<=>\\\00': + escaped += '\\' + c + state = STATE_ANY + else: + escaped += '\\\\' + c + elif state == STATE_ESCAPE_HEX: + if c in hexdigits: + escaped += '\\' + tmp_buffer + c + else: + escaped += '\\\\' + tmp_buffer + c + tmp_buffer = '' + state = STATE_ANY + + # final state + if state == STATE_ESCAPE: + escaped += '\\\\' + elif state == STATE_ESCAPE_HEX: + escaped += '\\\\' + tmp_buffer + + if escaped[0] == ' ': # leading SPACE must be escaped + escaped = '\\' + escaped + + if escaped[-1] == ' ' and len(escaped) > 1 and escaped[-2] != '\\': # trailing SPACE must be escaped + escaped = escaped[:-1] + '\\ ' + + return escaped -- cgit