ldapcherry/ldapcherry/backend/backendLdap.py

658 lines
23 KiB
Python
Raw Normal View History

2015-04-15 21:13:14 +02:00
# -*- coding: utf-8 -*-
# vim:set expandtab tabstop=4 shiftwidth=4:
#
# The MIT License (MIT)
# LdapCherry
# Copyright (c) 2014 Carpentier Pierre-Francois
2015-05-20 17:13:18 +02:00
import cherrypy
import ldap
import ldap.modlist as modlist
2015-07-15 21:28:54 +02:00
import ldap.filter
2015-05-20 17:13:18 +02:00
import logging
import ldapcherry.backend
import sys
from ldapcherry.exceptions import UserDoesntExist, \
GroupDoesntExist, \
UserAlreadyExists
import os
import re
2019-02-07 20:16:39 +01:00
if sys.version < '3':
from sets import Set as set
PYTHON_LDAP_MAJOR_VERSION = ldap.__version__[0]
2015-07-10 21:06:28 +02:00
2019-02-09 12:05:09 +01:00
class CaFileDontExist(Exception):
def __init__(self, cafile):
self.cafile = cafile
self.log = "CA file %(cafile)s does not exist" % {'cafile': cafile}
class MissingGroupAttr(Exception):
def __init__(self, attr):
self.attr = attr
self.log = "User doesn't have %(attr)s in its attributes" \
", cannot use it to set group" % {'attr': attr}
class MultivaluedGroupAttr(Exception):
def __init__(self, attr):
self.attr = cafile
self.log = "User's attribute '%(attr)s' is multivalued" \
", cannot use it to set group" % {'attr': attr}
2015-07-10 21:06:28 +02:00
NO_ATTR = 0
DISPLAYED_ATTRS = 1
LISTED_ATTRS = 2
ALL_ATTRS = 3
2015-07-10 21:06:28 +02:00
2015-04-15 21:13:14 +02:00
class Backend(ldapcherry.backend.Backend):
2015-05-31 18:40:35 +02:00
def __init__(self, config, logger, name, attrslist, key):
2015-07-29 08:15:54 +02:00
"""Backend initialization"""
# Recover all the parameters
2015-05-20 17:13:18 +02:00
self.config = config
self._logger = logger
self.backend_name = name
self.backend_display_name = self.get_param('display_name')
self.binddn = self.get_param('binddn')
self.bindpassword = self.get_param('password')
self.ca = self.get_param('ca', False)
self.checkcert = self.get_param('checkcert', 'on')
self.starttls = self.get_param('starttls', 'off')
self.uri = self.get_param('uri')
self.timeout = self.get_param('timeout', 1)
self.userdn = self.get_param('userdn')
self.groupdn = self.get_param('groupdn')
self.user_filter_tmpl = self.get_param('user_filter_tmpl')
2015-05-25 18:52:14 +02:00
self.group_filter_tmpl = self.get_param('group_filter_tmpl')
self.search_filter_tmpl = self.get_param('search_filter_tmpl')
self.dn_user_attr = self.get_param('dn_user_attr')
self.objectclasses = []
2015-05-31 18:40:35 +02:00
self.key = key
2015-07-29 08:15:54 +02:00
# objectclasses parameter is a coma separated list in configuration
# split it to get a real list, and convert it to bytes
2019-02-07 20:16:39 +01:00
for o in re.split(r'\W+', self.get_param('objectclasses')):
self.objectclasses.append(self._byte_p23(o))
self.group_attrs = {}
self.group_attrs_keys = set([])
for param in config:
name, sep, group = param.partition('.')
if name == 'group_attr':
self.group_attrs[group] = self.get_param(param)
self.group_attrs_keys |= set(
self._extract_format_keys(self.get_param(param))
)
self.attrlist = []
for a in attrslist:
self.attrlist.append(self._byte_p2(a))
2015-07-29 08:15:54 +02:00
# exception handler (mainly to log something meaningful)
def _exception_handler(self, e):
2015-07-29 08:15:54 +02:00
""" Exception handling"""
et = type(e)
if et is ldap.OPERATIONS_ERROR:
2015-07-10 21:06:28 +02:00
self._logger(
2015-07-11 22:25:21 +02:00
severity=logging.ERROR,
msg="cannot use starttls with ldaps://"
" uri (uri: " + self.uri + ")",
2015-07-10 21:06:28 +02:00
)
elif et is ldap.INVALID_CREDENTIALS:
self._logger(
2015-07-11 22:25:21 +02:00
severity=logging.ERROR,
msg="Configuration error, wrong credentials,"
" unable to connect to ldap with '" + self.binddn + "'",
)
elif et is ldap.SERVER_DOWN:
self._logger(
2015-07-11 22:25:21 +02:00
severity=logging.ERROR,
msg="Unable to contact ldap server '" +
self.uri +
"', check 'auth.ldap.uri'"
" and ssl/tls configuration",
)
elif et is ldap.FILTER_ERROR:
self._logger(
2015-07-11 22:25:21 +02:00
severity=logging.ERROR,
msg="Bad search filter, check '" +
self.backend_name +
".*_filter_tmpl' params",
)
elif et is ldap.NO_SUCH_OBJECT:
self._logger(
2015-07-11 22:25:21 +02:00
severity=logging.ERROR,
msg="DN doesn't exist, check '" +
2015-07-11 22:25:21 +02:00
self.backend_name +
".userdn'or '" +
2015-07-11 22:25:21 +02:00
self.backend_name +
".groupdn'",
)
elif et is ldap.OBJECT_CLASS_VIOLATION:
info = e.args[0]['info']
desc = e.args[0]['desc']
self._logger(
2015-07-11 22:25:21 +02:00
severity=logging.ERROR,
msg="Configuration error, " + desc + ", " + info,
)
elif et is ldap.INSUFFICIENT_ACCESS:
self._logger(
2015-07-11 22:25:21 +02:00
severity=logging.ERROR,
msg="Access error on '" +
self.backend_name +
2015-07-29 08:15:54 +02:00
"' backend, please check your acls in backend " +
self.backend_name,
)
elif et is ldap.ALREADY_EXISTS:
desc = e.args[0]['desc']
self._logger(
2015-07-11 22:25:21 +02:00
severity=logging.ERROR,
msg="adding user failed, " + desc,
)
else:
self._logger(
2015-07-11 22:25:21 +02:00
severity=logging.ERROR,
2015-07-29 08:15:54 +02:00
msg="unknow exception in backend " + self.backend_name,
)
raise
def _extract_format_keys(self, fmt_string):
"""Extract the keys of a format string
(the 'stuff' in '%(stuff)s'
"""
class AccessSaver:
def __init__(self):
self.keys = []
def __getitem__(self, key):
self.keys.append(key)
a = AccessSaver()
fmt_string % a
return a.keys
def _normalize_group_attrs(self, attrs):
"""Normalize the attributes used to set groups
If it's a list of one element, it just become this
element.
It raises an error if the attribute doesn't exist
or if it's multivaluated.
"""
for key in self.group_attrs_keys:
if key not in attrs:
raise MissingGroupAttr(key)
if type(attrs[key]) is list and len(attrs[key]) == 1:
attrs[key] = attrs[key][0]
if type(attrs[key]) is list and len(attrs[key]) != 1:
raise MultivaluedGroupAttr(key)
2015-05-28 09:45:10 +02:00
def _connect(self):
2015-07-29 08:15:54 +02:00
"""Initialize an ldap client"""
2015-05-28 09:45:10 +02:00
ldap_client = ldap.initialize(self.uri)
ldap.set_option(ldap.OPT_REFERRALS, 0)
ldap.set_option(ldap.OPT_TIMEOUT, self.timeout)
2015-05-28 09:45:10 +02:00
if self.starttls == 'on':
ldap.set_option(ldap.OPT_X_TLS_DEMAND, True)
2015-05-28 09:45:10 +02:00
else:
ldap.set_option(ldap.OPT_X_TLS_DEMAND, False)
2015-07-29 08:15:54 +02:00
# set the CA file if declared and if necessary
2015-05-28 09:45:10 +02:00
if self.ca and self.checkcert == 'on':
2015-07-29 08:15:54 +02:00
# check if the CA file actually exists
if os.path.isfile(self.ca):
ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, self.ca)
else:
raise CaFileDontExist(self.ca)
2015-05-28 09:45:10 +02:00
if self.checkcert == 'off':
# this is dark magic
# remove any of these two lines and it doesn't work
ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
2015-07-11 22:25:21 +02:00
ldap_client.set_option(
ldap.OPT_X_TLS_REQUIRE_CERT,
ldap.OPT_X_TLS_NEVER
)
2015-05-28 09:45:10 +02:00
else:
# this is even darker magic
2015-07-11 22:25:21 +02:00
ldap_client.set_option(
ldap.OPT_X_TLS_REQUIRE_CERT,
ldap.OPT_X_TLS_DEMAND
)
# it doesn't make sense to set it to never
# (== don't check certifate)
# but it only works with this option...
# ... and it checks the certificat
# (I've lost my sanity over this)
2015-07-11 22:25:21 +02:00
ldap.set_option(
ldap.OPT_X_TLS_REQUIRE_CERT,
ldap.OPT_X_TLS_NEVER
)
2015-06-06 22:23:21 +02:00
if self.starttls == 'on':
2015-05-28 09:45:10 +02:00
try:
ldap_client.start_tls_s()
except Exception as e:
self._exception_handler(e)
2015-05-28 09:45:10 +02:00
return ldap_client
def _bind(self):
2015-07-29 08:15:54 +02:00
"""bind to the ldap with the technical account"""
2015-05-28 09:45:10 +02:00
ldap_client = self._connect()
try:
ldap_client.simple_bind_s(self.binddn, self.bindpassword)
except Exception as e:
2015-05-28 09:45:10 +02:00
ldap_client.unbind_s()
self._exception_handler(e)
2015-05-28 09:45:10 +02:00
return ldap_client
def _search(self, searchfilter, attrs, basedn):
2015-07-29 08:15:54 +02:00
"""Generic search"""
if attrs == NO_ATTR:
attrlist = []
elif attrs == DISPLAYED_ATTRS:
# fix me later (to much attributes)
attrlist = self.attrlist
elif attrs == LISTED_ATTRS:
attrlist = self.attrlist
elif attrs == ALL_ATTRS:
attrlist = None
else:
attrlist = None
2015-07-29 08:15:54 +02:00
# bind and search the ldap
2015-05-28 09:45:10 +02:00
ldap_client = self._bind()
try:
2015-07-11 22:25:21 +02:00
r = ldap_client.search_s(
basedn,
ldap.SCOPE_SUBTREE,
searchfilter,
attrlist=attrlist
)
except Exception as e:
2015-05-28 09:45:10 +02:00
ldap_client.unbind_s()
self._exception_handler(e)
2015-05-28 09:45:10 +02:00
ldap_client.unbind_s()
2015-07-28 23:27:02 +02:00
2015-07-29 08:15:54 +02:00
# python-ldap doesn't know utf-8,
# it treates everything as bytes.
# So it's necessary to reencode
# it's output in utf-8.
2015-07-28 23:27:02 +02:00
ret = []
for entry in r:
uni_dn = self._uni(entry[0])
uni_attrs = {}
for attr in entry[1]:
if type(entry[1][attr]) is list:
tmp = []
for value in entry[1][attr]:
tmp.append(self._uni(value))
else:
tmp = self._uni(entry[1][attr])
uni_attrs[self._uni(attr)] = tmp
ret.append((uni_dn, uni_attrs))
return ret
2015-05-28 09:45:10 +02:00
def _get_user(self, username, attrs=ALL_ATTRS):
2015-07-29 08:15:54 +02:00
"""Get a user from the ldap"""
2015-05-28 09:45:10 +02:00
2015-07-15 21:28:54 +02:00
username = ldap.filter.escape_filter_chars(username)
2015-05-28 09:45:10 +02:00
user_filter = self.user_filter_tmpl % {
'username': self._uni(username)
2015-05-28 09:45:10 +02:00
}
r = self._search(self._byte_p2(user_filter), attrs, self.userdn)
2015-05-28 09:45:10 +02:00
if len(r) == 0:
return None
2015-07-29 08:15:54 +02:00
# if NO_ATTR, only return the DN
if attrs == NO_ATTR:
2015-05-28 09:45:10 +02:00
dn_entry = r[0][0]
2015-07-29 08:15:54 +02:00
# in other cases, return everything (dn + attributes)
else:
dn_entry = r[0]
2015-05-28 09:45:10 +02:00
return dn_entry
2015-07-29 08:15:54 +02:00
# python-ldap talks in bytes,
# as the rest of ldapcherry talks in unicode utf-8:
# * everything passed to python-ldap must be converted to bytes
# * everything coming from python-ldap must be converted to unicode
#
# The previous statement was true for python-ldap < version 3.X.
# With versions > 3.0.0 and python 3, it gets tricky,
# some parts of python-ldap takes string, specially the filters/escaper.
#
# so we have now:
# *_byte_p2 (unicode -> bytes conversion for python 2)
# *_byte_p3 (unicode -> bytes conversion for python 3)
# *_byte_p23 (unicode -> bytes conversion for python AND 3)
def _byte_p23(self, s):
"""unicode -> bytes conversion"""
if s is None:
return None
return s.encode('utf-8')
if sys.version < '3':
def _byte_p2(self, s):
"""unicode -> bytes conversion (python 2)"""
if s is None:
return None
return s.encode('utf-8')
2019-02-08 20:38:03 +01:00
def _byte_p3(self, s):
"""pass through (does something in python 3)"""
return s
def _uni(self, s):
"""bytes -> unicode conversion"""
if s is None:
return None
return s.decode('utf-8', 'ignore')
def attrs_pretreatment(self, attrs):
attrs_srt = {}
for a in attrs:
attrs_srt[self._byte_p2(a)] = self._modlist(
self._byte_p2(attrs[a])
)
return attrs_srt
else:
def _byte_p2(self, s):
"""pass through (does something in python 2)"""
return s
def _byte_p3(self, s):
"""unicode -> bytes conversion"""
if s is None:
return None
return s.encode('utf-8')
def _uni(self, s):
"""bytes -> unicode conversion"""
if s is None:
return None
if type(s) is not str:
return s.decode('utf-8', 'ignore')
else:
return s
2015-05-20 17:13:18 +02:00
def attrs_pretreatment(self, attrs):
attrs_srt = {}
for a in attrs:
attrs_srt[self._byte_p2(a)] = self._modlist(
self._byte_p3(attrs[a])
)
return attrs_srt
2015-05-20 17:13:18 +02:00
def auth(self, username, password):
2015-07-29 08:15:54 +02:00
"""Authentication of a user"""
2015-05-20 17:13:18 +02:00
binddn = self._get_user(self._byte_p2(username), NO_ATTR)
2015-07-11 22:25:21 +02:00
if binddn is not None:
2015-05-20 17:13:18 +02:00
ldap_client = self._connect()
try:
ldap_client.simple_bind_s(
self._byte_p2(binddn),
self._byte_p2(password)
)
2015-05-20 17:13:18 +02:00
except ldap.INVALID_CREDENTIALS:
ldap_client.unbind_s()
return False
ldap_client.unbind_s()
return True
else:
return False
2016-06-17 00:10:02 +02:00
if PYTHON_LDAP_MAJOR_VERSION == '2':
@staticmethod
def _modlist(in_attr):
return in_attr
else:
@staticmethod
def _modlist(in_attr):
return [in_attr]
def add_user(self, attrs):
2015-07-29 08:15:54 +02:00
"""add a user"""
ldap_client = self._bind()
2015-07-29 08:15:54 +02:00
# encoding crap
attrs_srt = self.attrs_pretreatment(attrs)
2016-06-17 00:10:02 +02:00
attrs_srt[self._byte_p2('objectClass')] = self.objectclasses
2015-07-29 08:15:54 +02:00
# construct is DN
2015-07-11 22:25:21 +02:00
dn = \
self._byte_p2(self.dn_user_attr) + \
self._byte_p2('=') + \
self._byte_p2(ldap.dn.escape_dn_chars(
attrs[self.dn_user_attr]
)
) + \
self._byte_p2(',') + \
self._byte_p2(self.userdn)
# gen the ldif first add_s and add the user
ldif = modlist.addModlist(attrs_srt)
try:
2015-07-10 21:06:28 +02:00
ldap_client.add_s(dn, ldif)
except ldap.ALREADY_EXISTS as e:
raise UserAlreadyExists(attrs[self.key], self.backend_name)
except Exception as e:
ldap_client.unbind_s()
self._exception_handler(e)
ldap_client.unbind_s()
2015-05-20 17:13:18 +02:00
def del_user(self, username):
2015-07-29 08:15:54 +02:00
"""delete a user"""
ldap_client = self._bind()
2015-07-29 08:15:54 +02:00
# recover the user dn
dn = self._byte_p2(self._get_user(self._byte_p2(username), NO_ATTR))
2015-07-29 08:15:54 +02:00
# delete
2015-07-11 22:25:21 +02:00
if dn is not None:
ldap_client.delete_s(dn)
else:
2015-07-29 08:15:54 +02:00
ldap_client.unbind_s()
raise UserDoesntExist(username, self.backend_name)
ldap_client.unbind_s()
2015-05-20 17:13:18 +02:00
def set_attrs(self, username, attrs):
""" set user attributes"""
ldap_client = self._bind()
tmp = self._get_user(self._byte_p2(username), ALL_ATTRS)
if tmp is None:
raise UserDoesntExist(username, self.backend_name)
dn = self._byte_p2(tmp[0])
2015-07-05 22:48:24 +02:00
old_attrs = tmp[1]
for attr in attrs:
bcontent = self._byte_p2(attrs[attr])
battr = self._byte_p2(attr)
new = {battr: self._modlist(self._byte_p3(bcontent))}
2015-07-28 00:18:05 +02:00
# if attr is dn entry, use rename
if attr.lower() == self.dn_user_attr.lower():
ldap_client.rename_s(
dn,
2015-07-28 23:27:02 +02:00
ldap.dn.dn2str([[(battr, bcontent, 1)]])
2015-07-28 00:18:05 +02:00
)
dn = ldap.dn.dn2str(
[[(battr, bcontent, 1)]] + ldap.dn.str2dn(dn)[1:]
)
else:
2015-07-29 08:15:54 +02:00
# if attr is already set, replace the value
# (see dict old passed to modifyModlist)
2015-07-28 00:18:05 +02:00
if attr in old_attrs:
2015-07-28 23:27:02 +02:00
if type(old_attrs[attr]) is list:
tmp = []
for value in old_attrs[attr]:
tmp.append(self._byte_p2(value))
2015-07-28 23:27:02 +02:00
bold_value = tmp
else:
bold_value = self._modlist(
self._byte_p3(old_attrs[attr])
)
2015-07-28 23:27:02 +02:00
old = {battr: bold_value}
2015-07-29 08:15:54 +02:00
# attribute is not set, just add it
2015-07-28 00:18:05 +02:00
else:
old = {}
ldif = modlist.modifyModlist(old, new)
if ldif:
try:
ldap_client.modify_s(dn, ldif)
except Exception as e:
ldap_client.unbind_s()
self._exception_handler(e)
ldap_client.unbind_s()
2015-05-24 17:32:03 +02:00
def add_to_groups(self, username, groups):
ldap_client = self._bind()
2015-07-29 08:15:54 +02:00
# recover dn of the user and his attributes
tmp = self._get_user(self._byte_p2(username), ALL_ATTRS)
dn = tmp[0]
2015-07-05 22:48:24 +02:00
attrs = tmp[1]
attrs['dn'] = dn
self._normalize_group_attrs(attrs)
dn = self._byte_p2(tmp[0])
2015-07-29 08:15:54 +02:00
# add user to all groups
for group in groups:
group = self._byte_p2(group)
2015-07-29 08:15:54 +02:00
# iterate on group membership attributes
for attr in self.group_attrs:
2015-07-29 08:15:54 +02:00
# fill the content template
content = self._byte_p2(self.group_attrs[attr] % attrs)
self._logger(
2015-07-10 21:06:28 +02:00
severity=logging.DEBUG,
2015-07-11 22:25:21 +02:00
msg="%(backend)s: adding user '%(user)s'"
" with dn '%(dn)s' to group '%(group)s' by"
" setting '%(attr)s' to '%(content)s'" % {
'user': username,
2015-07-28 23:27:02 +02:00
'dn': self._uni(dn),
2015-07-29 08:15:54 +02:00
'group': self._uni(group),
2015-07-11 22:25:21 +02:00
'attr': attr,
2015-07-28 23:27:02 +02:00
'content': self._uni(content),
2015-07-11 22:25:21 +02:00
'backend': self.backend_name
}
)
2019-02-09 12:05:09 +01:00
ldif = modlist.modifyModlist(
{},
{attr: self._modlist(self._byte_p3(content))}
2019-02-09 12:05:09 +01:00
)
2015-06-16 23:56:12 +02:00
try:
print(ldif)
print(group)
2015-06-16 23:56:12 +02:00
ldap_client.modify_s(group, ldif)
2015-07-29 08:15:54 +02:00
# if already member, not a big deal, just log it and continue
except (ldap.TYPE_OR_VALUE_EXISTS, ldap.ALREADY_EXISTS) as e:
self._logger(
2015-07-10 21:06:28 +02:00
severity=logging.INFO,
2015-07-11 22:25:21 +02:00
msg="%(backend)s: user '%(user)s'"
" already member of group '%(group)s'"
" (attribute '%(attr)s')" % {
2015-07-11 22:25:21 +02:00
'user': username,
2015-07-29 08:15:54 +02:00
'group': self._uni(group),
2015-07-11 22:25:21 +02:00
'attr': attr,
'backend': self.backend_name
}
)
except ldap.NO_SUCH_OBJECT as e:
raise GroupDoesntExist(group, self.backend_name)
except Exception as e:
ldap_client.unbind_s()
self._exception_handler(e)
ldap_client.unbind_s()
2015-07-05 22:48:24 +02:00
def del_from_groups(self, username, groups):
2015-07-29 08:15:54 +02:00
"""Delete user from groups"""
# it follows the same logic than add_to_groups
# but with MOD_DELETE
ldap_client = self._bind()
tmp = self._get_user(self._byte_p2(username), ALL_ATTRS)
if tmp is None:
raise UserDoesntExist(username, self.backend_name)
dn = tmp[0]
2015-07-05 22:48:24 +02:00
attrs = tmp[1]
attrs['dn'] = dn
self._normalize_group_attrs(attrs)
dn = self._byte_p2(tmp[0])
for group in groups:
group = self._byte_p2(group)
for attr in self.group_attrs:
content = self._byte_p2(self.group_attrs[attr] % attrs)
ldif = [(ldap.MOD_DELETE, attr, self._byte_p3(content))]
2015-06-16 23:56:12 +02:00
try:
ldap_client.modify_s(group, ldif)
except ldap.NO_SUCH_ATTRIBUTE as e:
self._logger(
2015-07-10 21:06:28 +02:00
severity=logging.INFO,
2015-07-11 22:25:21 +02:00
msg="%(backend)s: user '%(user)s'"
" wasn't member of group '%(group)s'"
" (attribute '%(attr)s')" % {
'user': username,
2015-07-29 08:15:54 +02:00
'group': self._uni(group),
2015-07-11 22:25:21 +02:00
'attr': attr,
'backend': self.backend_name
}
)
except Exception as e:
ldap_client.unbind_s()
self._exception_handler(e)
ldap_client.unbind_s()
2015-05-25 19:52:54 +02:00
def search(self, searchstring):
2015-07-29 08:15:54 +02:00
"""Search users"""
# escape special char to avoid injection
searchstring = ldap.filter.escape_filter_chars(
self._byte_p2(searchstring)
)
2015-07-29 08:15:54 +02:00
# fill the search string template
2015-05-25 19:52:54 +02:00
searchfilter = self.search_filter_tmpl % {
'searchstring': searchstring
}
2015-07-29 08:15:54 +02:00
ret = {}
# search an process the result a little
for u in self._search(searchfilter, DISPLAYED_ATTRS, self.userdn):
2015-05-31 18:40:35 +02:00
attrs = {}
attrs_tmp = u[1]
2015-06-06 22:23:21 +02:00
for attr in attrs_tmp:
2015-05-31 18:40:35 +02:00
value_tmp = attrs_tmp[attr]
if len(value_tmp) == 1:
2015-07-28 23:27:02 +02:00
attrs[attr] = value_tmp[0]
2015-05-31 18:40:35 +02:00
else:
2015-07-28 23:27:02 +02:00
attrs[attr] = value_tmp
2015-06-06 22:23:21 +02:00
2015-05-31 18:40:35 +02:00
if self.key in attrs:
ret[attrs[self.key]] = attrs
2015-06-06 22:23:21 +02:00
return ret
2015-05-25 19:52:54 +02:00
2015-05-26 22:50:42 +02:00
def get_user(self, username):
2015-07-29 08:15:54 +02:00
"""Gest a specific user"""
2015-05-26 22:50:42 +02:00
ret = {}
tmp = self._get_user(self._byte_p2(username), ALL_ATTRS)
if tmp is None:
raise UserDoesntExist(username, self.backend_name)
attrs_tmp = tmp[1]
2015-06-06 22:23:21 +02:00
for attr in attrs_tmp:
2015-05-26 22:50:42 +02:00
value_tmp = attrs_tmp[attr]
if len(value_tmp) == 1:
2015-07-28 23:27:02 +02:00
ret[attr] = value_tmp[0]
2015-05-26 22:50:42 +02:00
else:
2015-07-28 23:27:02 +02:00
ret[attr] = value_tmp
2015-06-06 22:23:21 +02:00
return ret
2015-05-26 22:50:42 +02:00
2015-05-28 09:45:10 +02:00
def get_groups(self, username):
2015-07-29 08:15:54 +02:00
"""Get all groups of a user"""
username = ldap.filter.escape_filter_chars(self._byte_p2(username))
userdn = self._get_user(username, NO_ATTR)
2015-06-06 22:23:21 +02:00
2015-05-28 09:45:10 +02:00
searchfilter = self.group_filter_tmpl % {
'userdn': userdn,
'username': username
}
2015-05-20 17:13:18 +02:00
groups = self._search(searchfilter, NO_ATTR, self.groupdn)
2015-05-28 09:45:10 +02:00
ret = []
for entry in groups:
ret.append(self._uni(entry[0]))
2015-05-28 09:45:10 +02:00
return ret