summaryrefslogtreecommitdiff
path: root/pynslcd/group.py
diff options
context:
space:
mode:
authorArthur de Jong <arthur@arthurdejong.org>2013-03-24 22:52:44 +0100
committerArthur de Jong <arthur@arthurdejong.org>2013-03-24 22:52:44 +0100
commit3daa68d35cf18c0dc80c8c24c7aa23c6273d06c4 (patch)
tree3b1e8c1596f292dbe67fb1cc903237de0466be66 /pynslcd/group.py
parentedd119c3a0d532fc5f87ccf89585370cb2fa3fed (diff)
parent642064cc205cf484bd904d94141eba8740aa0a28 (diff)
Implement support for nested groups
Diffstat (limited to 'pynslcd/group.py')
-rw-r--r--pynslcd/group.py55
1 files changed, 45 insertions, 10 deletions
diff --git a/pynslcd/group.py b/pynslcd/group.py
index a43aae5..71a1173 100644
--- a/pynslcd/group.py
+++ b/pynslcd/group.py
@@ -22,9 +22,11 @@ import itertools
import logging
from ldap.filter import escape_filter_chars
+import ldap
from passwd import dn2uid, uid2dn
import cache
+import cfg
import common
import constants
import search
@@ -51,7 +53,7 @@ class Search(search.LDAPSearch):
def __init__(self, *args, **kwargs):
super(Search, self).__init__(*args, **kwargs)
- if 'memberUid' in self.parameters:
+ if 'memberUid' in self.parameters or 'member' in self.parameters:
# set up our own attributes that leave out membership attributes
self.attributes = list(self.attributes)
self.attributes.remove(attmap['memberUid'])
@@ -95,24 +97,39 @@ class GroupRequest(common.Request):
self.fp.write_int32(gid)
self.fp.write_stringlist(members)
- def convert(self, dn, attributes, parameters):
- # get group names and check against requested group name
- names = attributes['cn']
- # get group group password
- passwd = attributes['userPassword'][0]
- # get group id(s)
- gids = [int(x) for x in attributes['gidNumber']]
- # build member list
- members = set()
+ def get_members(self, attributes, members, subgroups, seen):
# add the memberUid values
for member in clean(attributes['memberUid']):
if common.isvalidname(member):
members.add(member)
# translate and add the member values
for memberdn in clean(attributes['member']):
+ if memberdn in seen:
+ continue
+ seen.add(memberdn)
member = dn2uid(self.conn, memberdn)
if member and common.isvalidname(member):
members.add(member)
+ elif cfg.nss_nested_groups:
+ subgroups.append(memberdn)
+
+ def convert(self, dn, attributes, parameters):
+ # get group names and check against requested group name
+ names = attributes['cn']
+ # get group group password
+ passwd = attributes['userPassword'][0]
+ # get group id(s)
+ gids = [int(x) for x in attributes['gidNumber']]
+ # build member list
+ members = set()
+ subgroups = []
+ seen = set([dn])
+ self.get_members(attributes, members, subgroups, seen)
+ # go over subgroups to find more members
+ while subgroups:
+ memberdn = subgroups.pop(0)
+ for dn2, attributes2 in self.search(self.conn, base=memberdn, scope=ldap.SCOPE_BASE):
+ self.get_members(attributes2, members, subgroups, seen)
# actually return the results
for name in names:
if not common.isvalidname(name):
@@ -150,6 +167,24 @@ class GroupByMemberRequest(GroupRequest):
common.validate_name(memberuid)
return dict(memberUid=memberuid)
+ def get_results(self, parameters):
+ seen = set()
+ for dn, attributes in self.search(self.conn, parameters=parameters):
+ seen.add(dn)
+ for values in self.convert(dn, attributes, parameters):
+ yield values
+ if cfg.nss_nested_groups:
+ tocheck = list(seen)
+ # find parent groups
+ while tocheck:
+ group = tocheck.pop(0)
+ for dn, attributes in self.search(self.conn, parameters=dict(member=group)):
+ if dn not in seen:
+ seen.add(dn)
+ tocheck.append(dn)
+ for result in self.convert(dn, attributes, parameters):
+ yield result
+
class GroupAllRequest(GroupRequest):