changeset 5870:7b9f39289e16

security fix: fix virtual group bug in ACL evaluation, add a test for it affected moin releases: all 1.9 releases up to and including 1.9.4 moin releases < 1.9 are NOT affected. You can find out the moin version by looking at SystemInfo page or at the output of <<SystemInfo>> macro. Issue description: We have code that checks whether a group has special members "All" or "Known" or "Trusted", but there was a bug that checked whether these are present in the group NAME (not, as intended, in the group MEMBERS). a) If you have group MEMBERS like "All" or "Known" or "Trusted", they did not work until now, but will start working with this changeset. E.g. SomeGroup: * JoeDoe * Trusted SomeGroup will now (correctly) include JoeDoe and also all trusted users. It (erroneously) contained only "JoeDoe" and "Trusted" (as a username, not as a virtual group) before. b) If you have group NAMES containing "All" or "Known" or "Trusted", they behaved wrong until now (they erroneously included All/Known/Trusted users even if you did not list them as members), but will start working correctly with this changeset. E.g. AllFriendsGroup: * JoeDoe AllFriendsGroup will now (correctly) include only JoeDoe. It (erroneously) contained all users (including JoeDoe) before. E.g. MyTrustedFriendsGroup: * JoeDoe MyTrustedFriendsGroup will now (correctly) include only JoeDoe. It (erroneously) contained all trusted users and JoeDoe before.
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Mon, 03 Sep 2012 15:30:35 +0200
parents 0e58d9bcd3bd
children 2e90d7b58b42
files MoinMoin/security/__init__.py MoinMoin/security/_tests/test_security.py
diffstat 2 files changed, 49 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/security/__init__.py	Fri Aug 03 17:36:02 2012 +0200
+++ b/MoinMoin/security/__init__.py	Mon Sep 03 15:30:35 2012 +0200
@@ -320,11 +320,12 @@
                 handler = getattr(self, "_special_"+entry, None)
                 allowed = handler(request, name, dowhat, rightsdict)
             elif entry in groups:
-                if name in groups[entry]:
+                this_group = groups[entry]
+                if name in this_group:
                     allowed = rightsdict.get(dowhat)
                 else:
                     for special in self.special_users:
-                        if special in entry:
+                        if special in this_group:
                             handler = getattr(self, "_special_" + special, None)
                             allowed = handler(request, name, dowhat, rightsdict)
                             break # order of self.special_users is important
--- a/MoinMoin/security/_tests/test_security.py	Fri Aug 03 17:36:02 2012 +0200
+++ b/MoinMoin/security/_tests/test_security.py	Mon Sep 03 15:30:35 2012 +0200
@@ -16,10 +16,11 @@
 acliter = security.ACLStringIterator
 AccessControlList = security.AccessControlList
 
+from MoinMoin.datastruct import ConfigGroups
 from MoinMoin.PageEditor import PageEditor
 from MoinMoin.user import User
 
-from MoinMoin._tests import become_trusted, create_page, nuke_page
+from MoinMoin._tests import wikiconfig, become_trusted, create_page, nuke_page
 
 class TestACLStringIterator(object):
 
@@ -248,6 +249,50 @@
                 assert not acl.may(self.request, user, right)
 
 
+class TestGroupACL(object):
+
+    class Config(wikiconfig.Config):
+        def groups(self, request):
+            groups = {
+                u'PGroup': frozenset([u'Antony', u'Beatrice', ]),
+                u'AGroup': frozenset([u'All', ]),
+                # note: the next line is a INTENDED misnomer, there is "All" in
+                # the group NAME, but not in the group members. This makes
+                # sure that a bug that erroneously checked "in groupname" (instead
+                # of "in groupmembers") does not reappear.
+                u'AllGroup': frozenset([]), # note: intended misnomer
+            }
+            return ConfigGroups(request, groups)
+
+    def testApplyACLByGroup(self):
+        """ security: applying acl by group name"""
+        # This acl string...
+        acl_rights = [
+            "PGroup,AllGroup:read,write,admin "
+            "AGroup:read "
+            ]
+        acl = security.AccessControlList(self.request.cfg, acl_rights)
+
+        # Should apply these rights:
+        users = (
+            # user, rights
+            ('Antony', ('read', 'write', 'admin', )),  # in PGroup
+            ('Beatrice', ('read', 'write', 'admin', )),  # in PGroup
+            ('Charles', ('read', )),  # virtually in AGroup
+            )
+
+        # Check rights
+        for user, may in users:
+            mayNot = [right for right in self.request.cfg.acl_rights_valid
+                      if right not in may]
+            # User should have these rights...
+            for right in may:
+                assert acl.may(self.request, user, right)
+            # But NOT these:
+            for right in mayNot:
+                assert not acl.may(self.request, user, right)
+
+
 class TestPageAcls(object):
     """ security: real-life access control list on pages testing
     """