[Zope-Checkins] SVN: Zope/branches/2.9/ Collector #2072: Applied patch to fix problem with overly restrictive __bobo_traverse__ security and tests.

Alec Mitchell apm13 at columbia.edu
Thu Apr 20 20:26:16 EDT 2006


Log message for revision 67194:
  Collector #2072: Applied patch to fix problem with overly restrictive __bobo_traverse__ security and tests.
  

Changed:
  U   Zope/branches/2.9/doc/CHANGES.txt
  U   Zope/branches/2.9/lib/python/OFS/Traversable.py
  U   Zope/branches/2.9/lib/python/OFS/tests/testTraverse.py

-=-
Modified: Zope/branches/2.9/doc/CHANGES.txt
===================================================================
--- Zope/branches/2.9/doc/CHANGES.txt	2006-04-20 22:07:12 UTC (rev 67193)
+++ Zope/branches/2.9/doc/CHANGES.txt	2006-04-21 00:26:11 UTC (rev 67194)
@@ -17,6 +17,9 @@
   Zope 2.9.3 (UNRELEASED)
 
    Bugs fixed
+
+      - Collector #2072: Applied patch to fix problem with overly restrictive
+        __bobo_traverse__ security and tests.
       
       - Added missing Zope 3 packages: zope.app.intid, zope.app.keyreference, 
         zope.app.session, zope.contentprovider, zope.viewlet  

Modified: Zope/branches/2.9/lib/python/OFS/Traversable.py
===================================================================
--- Zope/branches/2.9/lib/python/OFS/Traversable.py	2006-04-20 22:07:12 UTC (rev 67193)
+++ Zope/branches/2.9/lib/python/OFS/Traversable.py	2006-04-21 00:26:11 UTC (rev 67194)
@@ -201,8 +201,20 @@
                         else:
                             # Can't determine container
                             container = _none
-                        if not securityManager.validate(
-                            obj, container, name, next):
+                        try:
+                            validated = securityManager.validate(
+                                                   obj, container, name, next)
+                        except Unauthorized:
+                            # If next is a simple unwrapped property, it's
+                            # parentage is indeterminate, but it may have been
+                            # acquired safely.  In this case validate will
+                            # raise an error, and we can explicitly check that
+                            # our value was acquired safely.
+                            validated = 0
+                            if container is _none and \
+                                   guarded_getattr(obj, name, marker) is next:
+                                validated = 1
+                        if not validated:
                             raise Unauthorized, name
                 else:
                     if restricted:

Modified: Zope/branches/2.9/lib/python/OFS/tests/testTraverse.py
===================================================================
--- Zope/branches/2.9/lib/python/OFS/tests/testTraverse.py	2006-04-20 22:07:12 UTC (rev 67193)
+++ Zope/branches/2.9/lib/python/OFS/tests/testTraverse.py	2006-04-21 00:26:11 UTC (rev 67194)
@@ -22,6 +22,7 @@
 import transaction
 import ZODB, Acquisition, transaction
 from AccessControl import SecurityManager, Unauthorized
+from AccessControl.Permissions import access_contents_information
 from AccessControl.SecurityManagement import newSecurityManager
 from AccessControl.SecurityManagement import noSecurityManager
 from Acquisition import aq_base
@@ -102,6 +103,16 @@
     bb_status = 'screechy'
 
 
+class BoboTraversableWithAcquisition(SimpleItem):
+    """
+       A BoboTraversable class which may use acquisition to find objects.
+       This is similar to how the __bobo_traverse__ added by Five behaves).
+    """
+
+    def __bobo_traverse__(self, request, name):
+        return Acquisition.aq_get(self, name)
+
+
 def makeConnection():
     import ZODB
     from ZODB.DemoStorage import DemoStorage
@@ -235,6 +246,58 @@
         self.failUnless(
             bb.restrictedTraverse('manufactured') is 42)
 
+    def testBoboTraverseToAcquiredObject(self):
+        # Verify it's possible to use a __bobo_traverse__ which retrieves
+        # objects by acquisition
+        noSecurityManager()
+        SecurityManager.setSecurityPolicy( self.oldPolicy )
+        bb = BoboTraversableWithAcquisition()
+        bb = bb.__of__(self.root)
+        self.assertEqual(
+            bb.restrictedTraverse('folder1'), bb.folder1)
+        self.assertEqual(
+            Acquisition.aq_inner(bb.restrictedTraverse('folder1')),
+            self.root.folder1)
+
+    def testBoboTraverseToAcquiredProtectedObject(self):
+        # Verify it's possible to use a __bobo_traverse__ which retrieves
+        # objects by acquisition
+        noSecurityManager()
+        SecurityManager.setSecurityPolicy( self.oldPolicy )
+        folder = self.root.folder1
+        # restrict the ability to access the retrieved object itself
+        folder.manage_permission(access_contents_information, [], 0)
+        bb = BoboTraversableWithAcquisition()
+        bb = bb.__of__(self.root)
+        self.failUnlessRaises(Unauthorized,
+                              self.root.folder1.restrictedTraverse, 'folder1')
+
+    def testBoboTraverseToAcquiredAttribute(self):
+        # Verify it's possible to use __bobo_traverse__ to an acquired
+        # attribute
+        noSecurityManager()
+        SecurityManager.setSecurityPolicy( self.oldPolicy )
+        folder = self.root.folder1
+        folder.stuff = 'stuff here'
+        bb = BoboTraversableWithAcquisition()
+        bb = bb.__of__(folder)
+        self.assertEqual(
+            bb.restrictedTraverse('stuff'), 'stuff here')
+
+    def testBoboTraverseToAcquiredProtectedAttribute(self):
+        # Verify that using __bobo_traverse__ to get an acquired but
+        # protected attribute results in Unauthorized
+        noSecurityManager()
+        SecurityManager.setSecurityPolicy( self.oldPolicy )
+        folder = self.root.folder1
+        # We protect the the attribute by restricting access to the parent
+        folder.manage_permission(access_contents_information, [], 0)
+        folder.stuff = 'stuff here'
+        bb = BoboTraversableWithAcquisition()
+        bb = bb.__of__(folder)
+        self.failUnlessRaises(Unauthorized,
+                              self.root.folder1.restrictedTraverse, 'stuff')
+
     def testAcquiredAttributeDenial(self):
         # Verify that restrictedTraverse raises the right kind of exception
         # on denial of access to an acquired attribute.  If it raises



More information about the Zope-Checkins mailing list