aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--radicale_auth_ldap/__init__.py7
-rw-r--r--radicale_auth_ldap/ldap3imports.py97
2 files changed, 102 insertions, 2 deletions
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 <http://www.gnu.org/licenses/>.
+"""
+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
bgstack15