mirror of
https://github.com/Kozea/Radicale.git
synced 2025-08-10 18:40:53 +00:00
Implementing the evalutaion of indirect group membership.
Now member or uniqueMember can also be used for the group membership.
This commit is contained in:
parent
8318feacce
commit
e3b5a6040b
3 changed files with 64 additions and 34 deletions
|
@ -18,13 +18,14 @@
|
|||
Authentication backend that checks credentials with a LDAP server.
|
||||
Following parameters are needed in the configuration:
|
||||
ldap_uri The LDAP URL to the server like ldap://localhost
|
||||
ldap_base The baseDN of the LDAP server
|
||||
ldap_base The baseDN of the LDAP server searching for users.
|
||||
ldap_reader_dn The DN of a LDAP user with read access to get the user accounts
|
||||
ldap_secret The password of the ldap_reader_dn
|
||||
ldap_secret_file The path of the file containing the password of the ldap_reader_dn
|
||||
ldap_filter The search filter to find the user to authenticate by the username
|
||||
ldap_user_attribute The attribute to be used as username after authentication
|
||||
ldap_groups_attribute The attribute containing group memberships in the LDAP user entry
|
||||
ldap_groups_base The baseDN of the LDAP server searching for groups.
|
||||
Following parameters controls SSL connections:
|
||||
ldap_use_ssl If ssl encryption should be used (to be deprecated)
|
||||
ldap_security The encryption mode to be used: *none*|tls|starttls
|
||||
|
@ -78,6 +79,9 @@ class Auth(auth.BaseAuth):
|
|||
self._ldap_filter = configuration.get("auth", "ldap_filter")
|
||||
self._ldap_user_attr = configuration.get("auth", "ldap_user_attribute")
|
||||
self._ldap_groups_attr = configuration.get("auth", "ldap_groups_attribute")
|
||||
self._ldap_groups_base = configuration.get("auth", "ldap_groups_base")
|
||||
if self._ldap_groups_base == "":
|
||||
self._ldap_groups_base = self._ldap_base
|
||||
ldap_secret_file_path = configuration.get("auth", "ldap_secret_file")
|
||||
if ldap_secret_file_path:
|
||||
with open(ldap_secret_file_path, 'r') as file:
|
||||
|
@ -130,8 +134,8 @@ class Auth(auth.BaseAuth):
|
|||
else:
|
||||
logger.info("auth.ldap_ssl_ca_file : (not provided)")
|
||||
"""Extend attributes to to be returned in the user query"""
|
||||
if self._ldap_groups_attr:
|
||||
self._ldap_attributes.append(self._ldap_groups_attr)
|
||||
if self._ldap_groups_attr == "memberOf":
|
||||
self._ldap_attributes.append("memberOf")
|
||||
if self._ldap_user_attr:
|
||||
self._ldap_attributes.append(self._ldap_user_attr)
|
||||
logger.info("ldap_attributes : %r" % self._ldap_attributes)
|
||||
|
@ -172,17 +176,25 @@ class Auth(auth.BaseAuth):
|
|||
conn.set_option(self.ldap.OPT_REFERRALS, 0)
|
||||
conn.simple_bind_s(user_dn, password)
|
||||
tmp: list[str] = []
|
||||
if self._ldap_groups_attr:
|
||||
tmp = []
|
||||
for g in user_entry[1][self._ldap_groups_attr]:
|
||||
"""Get group g's RDN's attribute value"""
|
||||
try:
|
||||
rdns = self.ldap.dn.explode_dn(g, notypes=True)
|
||||
tmp.append(rdns[0])
|
||||
except Exception:
|
||||
tmp.append(g.decode('utf8'))
|
||||
self._ldap_groups = set(tmp)
|
||||
logger.debug("_login2 LDAP groups of user: %s", ",".join(self._ldap_groups))
|
||||
gdns: list[str] = []
|
||||
if self._ldap_groups_attr == "memberOf":
|
||||
gdns = user_entry[1][self._ldap_groups_attr]
|
||||
elif self._ldap_groups_attr == "member" or self._ldap_groups_attr == "uniqueMember":
|
||||
res = conn.search_s(
|
||||
self._ldap_groups_base,
|
||||
self.ldap.SCOPE_SUBTREE,
|
||||
filterstr="({0}={1})".format(self._ldap_groups_attr,user_dn),
|
||||
attrlist=self._ldap_attributes
|
||||
)
|
||||
for g in gdns:
|
||||
"""Get group g's RDN's attribute value"""
|
||||
try:
|
||||
rdns = self.ldap.dn.explode_dn(g, notypes=True)
|
||||
tmp.append(rdns[0])
|
||||
except Exception:
|
||||
tmp.append(g.decode('utf8'))
|
||||
self._ldap_groups = set(tmp)
|
||||
logger.debug("_login2 LDAP groups of user: %s", ",".join(self._ldap_groups))
|
||||
if self._ldap_user_attr:
|
||||
if user_entry[1][self._ldap_user_attr]:
|
||||
tmplogin = user_entry[1][self._ldap_user_attr][0]
|
||||
|
@ -226,7 +238,7 @@ class Auth(auth.BaseAuth):
|
|||
except Exception as e:
|
||||
logger.debug(f"_login3 error 1 {e} (reader)")
|
||||
pass
|
||||
if not conn.bind():
|
||||
if not conn.bind(read_server_info=False):
|
||||
logger.debug("_login3 cannot bind (reader)")
|
||||
raise RuntimeError("Unable to read from LDAP server")
|
||||
logger.debug(f"_login3 bind as {self._ldap_reader_dn}")
|
||||
|
@ -257,19 +269,30 @@ class Auth(auth.BaseAuth):
|
|||
conn.start_tls()
|
||||
except self.ldap3.core.exceptions.LDAPStartTLSError as e:
|
||||
raise RuntimeError(f"_login3 StartTLS Error: {e}")
|
||||
if not conn.bind():
|
||||
if not conn.bind(read_server_info=False):
|
||||
logger.debug(f"_login3 user '{login}' cannot be found")
|
||||
return ""
|
||||
tmp: list[str] = []
|
||||
if self._ldap_groups_attr:
|
||||
tmp = []
|
||||
for g in user_entry['attributes'][self._ldap_groups_attr]:
|
||||
"""Get group g's RDN's attribute value"""
|
||||
try:
|
||||
rdns = self.ldap3.utils.dn.parse_dn(g)
|
||||
tmp.append(rdns[0][1])
|
||||
except Exception:
|
||||
tmp.append(g)
|
||||
gdns: list[str] = []
|
||||
"""Let's collect the groups of the user."""
|
||||
if self._ldap_groups_attr == "memberOf":
|
||||
gdns = user_entry['attributes']['memberOf']
|
||||
elif self._ldap_groups_attr == "member" or self._ldap_groups_attr == "uniqueMember":
|
||||
conn.search(
|
||||
search_base=self._ldap_groups_base,
|
||||
search_filter="({0}={1})".format(self._ldap_groups_attr,user_dn),
|
||||
search_scope=self.ldap3.SUBTREE,
|
||||
attributes="dn"
|
||||
)
|
||||
for group in conn.response:
|
||||
gdns.append(group['dn'])
|
||||
for g in gdns:
|
||||
"""Get group g's RDN's attribute value"""
|
||||
try:
|
||||
rdns = self.ldap3.utils.dn.parse_dn(g)
|
||||
tmp.append(rdns[0][1])
|
||||
except Exception:
|
||||
tmp.append(g)
|
||||
self._ldap_groups = set(tmp)
|
||||
logger.debug("_login3 LDAP groups of user: %s", ",".join(self._ldap_groups))
|
||||
if self._ldap_user_attr:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue