aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--radicale_auth_ldap/__init__.py94
-rw-r--r--setup.py12
2 files changed, 106 insertions, 0 deletions
diff --git a/radicale_auth_ldap/__init__.py b/radicale_auth_ldap/__init__.py
new file mode 100644
index 0000000..859c7c6
--- /dev/null
+++ b/radicale_auth_ldap/__init__.py
@@ -0,0 +1,94 @@
+# -*- coding: utf-8 -*-
+#
+# This file is part of Radicale Server - Calendar Server
+# Copyright © 2011 Corentin Le Bail
+# Copyright © 2011-2013 Guillaume Ayoub
+# Copyright © 2015 Raoul Thill
+# Copyright © 2017 Marco Huenseler
+#
+# This library is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This library 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Radicale. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+LDAP authentication.
+Authentication based on the ``ldap3`` module
+(https://github.com/cannatag/ldap3/).
+"""
+
+import ldap3
+import ldap3.utils.dn
+
+from radicale.auth import BaseAuth
+
+class Auth(BaseAuth):
+ def is_authenticated(self, user, password):
+ """Check if ``user``/``password`` couple is valid."""
+ SERVER = ldap3.Server(self.configuration.get("auth", "ldap_url"))
+ BASE = self.configuration.get("auth", "ldap_base")
+ ATTRIBUTE = self.configuration.get("auth", "ldap_attribute")
+ FILTER = self.configuration.get("auth", "ldap_filter")
+ BINDDN = self.configuration.get("auth", "ldap_binddn")
+ PASSWORD = self.configuration.get("auth", "ldap_password")
+ SCOPE = self.configuration.get("auth", "ldap_scope")
+
+ if BINDDN and PASSWORD:
+ conn = ldap3.Connection(SERVER, BINDDN, PASSWORD)
+ conn.bind()
+ else:
+ conn = ldap3.Connection(SERVER)
+
+ try:
+ self.logger.debug("LDAP whoami: %s" % conn.extend.standard.who_am_i())
+ except Exception as err:
+ self.logger.debug("LDAP error: %s" % err)
+
+ distinguished_name = "%s=%s" % (ATTRIBUTE, ldap3.utils.dn.escape_attribute_value(user))
+ self.logger.debug("LDAP bind for %s in base %s" % (distinguished_name, BASE))
+
+ if FILTER:
+ filter_string = "(&(%s)%s)" % (distinguished_name, FILTER)
+ else:
+ filter_string = distinguished_name
+ self.logger.debug("LDAP filter: %s" % filter_string)
+
+ conn.search(search_base=BASE,
+ search_scope=SCOPE,
+ search_filter=filter_string,
+ attributes=[ATTRIBUTE])
+
+ users = conn.response
+
+ if users:
+ user_dn = users[0]['dn']
+ uid = users[0]['attributes'][ATTRIBUTE]
+ self.logger.debug("LDAP user %s (%s) found" % (uid, user_dn))
+ try:
+ conn = ldap3.Connection(SERVER, user_dn, password)
+ conn.bind()
+ self.logger.debug(conn.result)
+ whoami = conn.extend.standard.who_am_i()
+ self.logger.debug("LDAP whoami: %s" % whoami)
+ if whoami:
+ self.logger.debug("LDAP bind OK")
+ return True
+ else:
+ self.logger.debug("LDAP bind failed")
+ return False
+ except ldap3.LDAPInvalidCredentialsResult:
+ self.logger.debug("LDAP invalid credentials")
+ except Exception as err:
+ self.logger.debug("LDAP error %s" % err)
+ return False
+ else:
+ self.logger.debug("LDAP user %s not found" % user)
+ return False
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..b10822a
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,12 @@
+#!/usr/bin/env python3
+
+from setuptools import setup
+
+setup(
+ name="radicale-auth-ldap",
+ version="0.1",
+ description="LDAP Authentication Plugin for Radicale 2",
+ author="Raoul Thill",
+ license="GNU GPL v3",
+ install_requires=["radicale>=2.0", "ldap3"],
+ packages=["radicale_auth_ldap"])
bgstack15