[Zope-Checkins] SVN: Zope/branches/accesscontrol-forward-port/ - An attempt to forward port Tres' fixes from Zope-2_7-branch to trunk. Tres or someone else should review this cause I don't feel comfortable enough to do it and there is one test failing at:

Sidnei da Silva sidnei at awkly.org
Fri Mar 18 05:24:22 EST 2005


Log message for revision 29550:
  
  - An attempt to forward port Tres' fixes from Zope-2_7-branch to trunk. Tres or someone else should review this cause I don't feel comfortable enough to do it and there is one test failing at:
  ERROR: test_bound_used_context_method_w_roles (AccessControl.tests.testBindings.TestBindings)
  

Changed:
  U   Zope/branches/accesscontrol-forward-port/doc/CHANGES.txt
  U   Zope/branches/accesscontrol-forward-port/lib/python/AccessControl/ImplPython.py
  U   Zope/branches/accesscontrol-forward-port/lib/python/AccessControl/cAccessControl.c
  A   Zope/branches/accesscontrol-forward-port/lib/python/AccessControl/tests/testAcquisition.py
  U   Zope/branches/accesscontrol-forward-port/lib/python/OFS/tests/testCopySupport.py

-=-
Modified: Zope/branches/accesscontrol-forward-port/doc/CHANGES.txt
===================================================================
--- Zope/branches/accesscontrol-forward-port/doc/CHANGES.txt	2005-03-18 10:21:52 UTC (rev 29549)
+++ Zope/branches/accesscontrol-forward-port/doc/CHANGES.txt	2005-03-18 10:24:22 UTC (rev 29550)
@@ -57,7 +57,11 @@
         text/<foo> types
 
     Bugs fixed
- 
+
+      - Forward-ported guarded_getattr fix: Restored ability to aquire
+        "through" unprotected contexts, broken through overzealous
+        cleanup in Zope 2.7.3.
+
       - Fixed Shared.DC.ZRDB.Results to behave with the new-style
         ExtensionClass. Added a test.
 

Modified: Zope/branches/accesscontrol-forward-port/lib/python/AccessControl/ImplPython.py
===================================================================
--- Zope/branches/accesscontrol-forward-port/lib/python/AccessControl/ImplPython.py	2005-03-18 10:21:52 UTC (rev 29549)
+++ Zope/branches/accesscontrol-forward-port/lib/python/AccessControl/ImplPython.py	2005-03-18 10:24:22 UTC (rev 29550)
@@ -17,6 +17,9 @@
 import string
 
 from Acquisition import aq_base
+from Acquisition import aq_parent
+from Acquisition import aq_inner
+from Acquisition import aq_acquire
 from ExtensionClass import Base
 from zLOG import LOG, PROBLEM
 
@@ -553,7 +556,13 @@
             # No veto, so we can return
             return v
 
+
+        # See if we can get the value doing a filtered acquire.
+        # aq_acquire will either return the same value as held by
+        # v or it will return an Unauthorized raised by validate.
         validate = SecurityManagement.getSecurityManager().validate
-        if validate(inst, inst, name, v):
-            return v
+        aq_acquire(inst, name, aq_validate, validate)
+        
+        return v
+        
     raise Unauthorized, name

Modified: Zope/branches/accesscontrol-forward-port/lib/python/AccessControl/cAccessControl.c
===================================================================
--- Zope/branches/accesscontrol-forward-port/lib/python/AccessControl/cAccessControl.c	2005-03-18 10:21:52 UTC (rev 29549)
+++ Zope/branches/accesscontrol-forward-port/lib/python/AccessControl/cAccessControl.c	2005-03-18 10:24:22 UTC (rev 29550)
@@ -2176,17 +2176,23 @@
             }
         }
 
-      /*
-        if validate(inst, inst, name, v):
-            return v
-       */
-      validate=callfunction4(validate, inst, inst, name, v);
-      if (validate==NULL) goto err;
-      i=PyObject_IsTrue(validate);
-      Py_DECREF(validate);
-      if (i < 0) goto err;
-      if (i > 0) return v;
-      
+      /* 
+        # See if we can get the value doing a filtered acquire.
+        # aq_acquire will either return the same value as held by
+        # v or it will return an Unauthorized raised by validate.
+        validate = SecurityManagement.getSecurityManager().validate
+        aq_acquire(inst, name, aq_validate, validate)
+        
+        return v
+      */
+
+      t = aq_Acquire(inst, name, aq_validate, validate, 1, NULL, 0);
+      if (t == NULL)
+        return NULL;
+      Py_DECREF(t);
+
+      return v;
+            
       unauthErr(name, v);
     err:
       Py_DECREF(v);
@@ -2378,4 +2384,3 @@
 	Py_DECREF(module);
 	module = NULL;
 }
-

Added: Zope/branches/accesscontrol-forward-port/lib/python/AccessControl/tests/testAcquisition.py
===================================================================
--- Zope/branches/accesscontrol-forward-port/lib/python/AccessControl/tests/testAcquisition.py	2005-03-18 10:21:52 UTC (rev 29549)
+++ Zope/branches/accesscontrol-forward-port/lib/python/AccessControl/tests/testAcquisition.py	2005-03-18 10:24:22 UTC (rev 29550)
@@ -0,0 +1,251 @@
+##############################################################################
+#
+# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+"""Tests demonstrating consequences of guarded_getattr fix from 2004/08/07
+
+   http://mail.zope.org/pipermail/zope-checkins/2004-August/028152.html
+   http://zope.org/Collectors/CMF/259
+
+"""
+
+import unittest
+
+from Testing.makerequest import makerequest
+
+import Zope2
+Zope2.startup()
+
+import transaction
+from OFS.SimpleItem import SimpleItem
+from Globals import InitializeClass
+from AccessControl import ClassSecurityInfo
+from AccessControl.SecurityManagement import newSecurityManager
+from AccessControl.SecurityManagement import noSecurityManager
+from AccessControl.Permissions import view, view_management_screens
+from AccessControl.ImplPython import guarded_getattr as guarded_getattr_py
+from AccessControl.ImplC import guarded_getattr as guarded_getattr_c
+from Products.SiteErrorLog.SiteErrorLog import SiteErrorLog
+
+
+class AllowedItem(SimpleItem):
+    id = 'allowed'
+    security = ClassSecurityInfo()
+    security.setDefaultAccess('allow')
+
+InitializeClass(AllowedItem)
+
+class DeniedItem(SimpleItem):
+    id = 'denied'
+    security = ClassSecurityInfo()
+    security.setDefaultAccess('deny')
+
+InitializeClass(DeniedItem)
+
+class ProtectedItem(SimpleItem):
+    id = 'protected'
+    security = ClassSecurityInfo()
+    security.declareObjectProtected(view_management_screens)
+
+InitializeClass(ProtectedItem)
+
+class ProtectedSiteErrorLog(SiteErrorLog):
+    '''This differs from the base by declaring security
+       for the object itself.
+    '''
+    id = 'error_log2'
+    security = ClassSecurityInfo()
+    security.declareObjectProtected(view)
+
+InitializeClass(ProtectedSiteErrorLog)
+
+
+class TestGetAttr(unittest.TestCase):
+
+    def setUp(self):
+        self.guarded_getattr = guarded_getattr_py
+        transaction.begin()
+        self.app = makerequest(Zope.app())
+        try:
+
+            # Set up a manager user
+            self.uf = self.app.acl_users
+            self.uf._doAddUser('manager', 'secret', ['Manager'], [])
+            self.login('manager')
+
+            # Set up objects in the root that we want to aquire
+            self.app.manage_addFolder('plain_folder')
+            self.app._setObject('error_log2', ProtectedSiteErrorLog())
+
+            # We also want to be able to acquire simple attributes
+            self.app.manage_addProperty(id='simple_type', type='string', value='a string')
+
+            # Set up a subfolder and the objects we want to acquire from
+            self.app.manage_addFolder('subfolder')
+            self.folder = self.app.subfolder
+            self.folder._setObject('allowed', AllowedItem())
+            self.folder._setObject('denied', DeniedItem())
+            self.folder._setObject('protected', ProtectedItem())
+
+        except:
+            self.tearDown()
+            raise
+
+    def tearDown(self):
+        noSecurityManager()
+        transaction.abort()
+        self.app._p_jar.close()
+
+    def login(self, name):
+        user = self.uf.getUserById(name)
+        user = user.__of__(self.uf)
+        newSecurityManager(None, user)
+
+    # Acquire plain folder
+
+    def testFolderAllowed(self):
+        o = self.guarded_getattr(self.folder.allowed, 'plain_folder')
+        self.assertEqual(o, self.app.plain_folder)
+
+    def testFolderDenied(self):
+        o = self.guarded_getattr(self.folder.denied, 'plain_folder')
+        self.assertEqual(o, self.app.plain_folder)
+
+    def testFolderProtected(self):
+        o = self.guarded_getattr(self.folder.protected, 'plain_folder')
+        self.assertEqual(o, self.app.plain_folder)
+
+    # Acquire user folder
+
+    def testAclUsersAllowed(self):
+        o = self.guarded_getattr(self.folder.allowed, 'acl_users')
+        self.assertEqual(o, self.app.acl_users)
+
+    def testAclUsersDenied(self):
+        # XXX: Fails in 2.7.3
+        o = self.guarded_getattr(self.folder.denied, 'acl_users')
+        self.assertEqual(o, self.app.acl_users)
+
+    def testAclUsersProtected(self):
+        # XXX: Fails in 2.7.3 for Anonymous
+        o = self.guarded_getattr(self.folder.protected, 'acl_users')
+        self.assertEqual(o, self.app.acl_users)
+
+    # Acquire browser id manager
+
+    def testBrowserIdManagerAllowed(self):
+        o = self.guarded_getattr(self.folder.allowed, 'browser_id_manager')
+        self.assertEqual(o, self.app.browser_id_manager)
+
+    def testBrowserIdManagerDenied(self):
+        o = self.guarded_getattr(self.folder.denied, 'browser_id_manager')
+        self.assertEqual(o, self.app.browser_id_manager)
+
+    def testBrowserIdManagerProtected(self):
+        o = self.guarded_getattr(self.folder.protected, 'browser_id_manager')
+        self.assertEqual(o, self.app.browser_id_manager)
+
+    # Acquire error log
+
+    def testErrorLogAllowed(self):
+        o = self.guarded_getattr(self.folder.allowed, 'error_log')
+        self.assertEqual(o, self.app.error_log)
+
+    def testErrorLogDenied(self):
+        # XXX: Fails in 2.7.3
+        o = self.guarded_getattr(self.folder.denied, 'error_log')
+        self.assertEqual(o, self.app.error_log)
+
+    def testErrorLogProtected(self):
+        # XXX: Fails in 2.7.3 for Anonymous
+        o = self.guarded_getattr(self.folder.protected, 'error_log')
+        self.assertEqual(o, self.app.error_log)
+
+    # Now watch this: error log with object security declaration works fine!
+
+    def testProtectedErrorLogAllowed(self):
+        o = self.guarded_getattr(self.folder.allowed, 'error_log2')
+        self.assertEqual(o, self.app.error_log2)
+
+    def testProtectedErrorLogDenied(self):
+        o = self.guarded_getattr(self.folder.denied, 'error_log2')
+        self.assertEqual(o, self.app.error_log2)
+
+    def testProtectedErrorLogProtected(self):
+        o = self.guarded_getattr(self.folder.protected, 'error_log2')
+        self.assertEqual(o, self.app.error_log2)
+
+    # This appears to mean that any potential acquiree must make sure
+    # to declareObjectProtected(SomePermission).
+
+    # From the ZDG:
+    # We've seen how to make  assertions on methods - but in the case of
+    # someObject we are not trying to access any particular method, but
+    # rather the object itself (to pass it to some_method). Because the
+    # security machinery will try to validate access to someObject, we
+    # need a way to let the security machinery know how to handle access
+    # to the object itself in addition to protecting its methods.
+
+    # IOW, acquiring an object in restricted Python now amounts to
+    # "passing it to some_method".
+
+
+    # Also test Richard Jones' use-case of acquiring a string:
+
+    def testSimpleTypeAllowed(self):
+        o = self.guarded_getattr(self.folder.allowed, 'simple_type')
+        self.assertEqual(o, 'a string')
+
+    def testSimpleTypeDenied(self):
+        # XXX: Fails in 2.7.3
+        o = self.guarded_getattr(self.folder.denied, 'simple_type')
+        self.assertEqual(o, 'a string')
+
+    def testSimpleTypeProtected(self):
+        # XXX: Fails in 2.7.3 for Anonymous
+        o = self.guarded_getattr(self.folder.protected, 'simple_type')
+        self.assertEqual(o, 'a string')
+
+
+class TestGetAttrAnonymous(TestGetAttr):
+
+    # Run all tests again as Anonymous User
+
+    def setUp(self):
+        TestGetAttr.setUp(self)
+        # Log out
+        noSecurityManager()
+
+
+class TestGetAttr_c(TestGetAttr):
+
+    def setUp(self):
+        TestGetAttr.setUp(self)
+        self.guarded_getattr = guarded_getattr_c
+
+class TestGetAttrAnonymous_c(TestGetAttrAnonymous):
+
+    def setUp(self):
+        TestGetAttrAnonymous.setUp(self)
+        self.guarded_getattr = guarded_getattr_c
+
+
+def test_suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(TestGetAttr))
+    suite.addTest(unittest.makeSuite(TestGetAttrAnonymous))
+    suite.addTest(unittest.makeSuite(TestGetAttr_c))
+    suite.addTest(unittest.makeSuite(TestGetAttrAnonymous_c))
+    return suite
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
+


Property changes on: Zope/branches/accesscontrol-forward-port/lib/python/AccessControl/tests/testAcquisition.py
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: Zope/branches/accesscontrol-forward-port/lib/python/OFS/tests/testCopySupport.py
===================================================================
--- Zope/branches/accesscontrol-forward-port/lib/python/OFS/tests/testCopySupport.py	2005-03-18 10:21:52 UTC (rev 29549)
+++ Zope/branches/accesscontrol-forward-port/lib/python/OFS/tests/testCopySupport.py	2005-03-18 10:24:22 UTC (rev 29550)
@@ -4,7 +4,7 @@
 from multifile import MultiFile
 
 import transaction
-from AccessControl import SecurityManager
+from AccessControl import SecurityManager, Unauthorized
 from AccessControl.SecurityManagement import newSecurityManager
 from AccessControl.SecurityManagement import noSecurityManager
 from Acquisition import Implicit
@@ -281,7 +281,9 @@
         self._lambdas = ( validate_lambda, checkPermission_lambda )
 
     def validate( self, *args, **kw ):
-        return self._lambdas[ 0 ]( *args, **kw )
+        if self._lambdas[ 0 ]( *args, **kw ):
+            return 1
+        raise Unauthorized
 
     def checkPermission( self, *args, **kw ) :
         return self._lambdas[ 1 ]( *args, **kw )



More information about the Zope-Checkins mailing list