Commit f8c22c39 authored by Shane Hathaway's avatar Shane Hathaway

Resolution for bug #558: when restrictedTraverse() traverses using a

__bobo_traverse__ hook, and the hook returns an object that comes from
some other container, the security policy may incorrectly deny access.
This fix determines the container of the object based on its
aquisition wrappers, if available, and passes it to validate().

Also added a corresponding unit test.
parent c2b16629
...@@ -12,8 +12,8 @@ ...@@ -12,8 +12,8 @@
############################################################################## ##############################################################################
'''This module implements a mix-in for traversable objects. '''This module implements a mix-in for traversable objects.
$Id: Traversable.py,v 1.15 2002/08/14 21:42:56 mj Exp $''' $Id: Traversable.py,v 1.16 2002/09/12 21:20:52 shane Exp $'''
__version__='$Revision: 1.15 $'[11:-2] __version__='$Revision: 1.16 $'[11:-2]
from Acquisition import Acquired, aq_inner, aq_parent, aq_base from Acquisition import Acquired, aq_inner, aq_parent, aq_base
...@@ -99,6 +99,7 @@ class Traversable: ...@@ -99,6 +99,7 @@ class Traversable:
object = self object = self
while path: while path:
name=pop() name=pop()
__traceback_info__ = path, name
if name[0] == '_': if name[0] == '_':
# Never allowed in a URL. # Never allowed in a URL.
...@@ -119,7 +120,11 @@ class Traversable: ...@@ -119,7 +120,11 @@ class Traversable:
if restricted: if restricted:
container = N container = N
if has(o, 'im_self'): if aq_base(o) is not o:
# The object is wrapped, so the acquisition
# context determines the container.
container = aq_parent(aq_inner(o))
elif has(o, 'im_self'):
container = o.im_self container = o.im_self
elif (has(get(object, 'aq_base', object), name) elif (has(get(object, 'aq_base', object), name)
and get(object, name) == o): and get(object, name) == o):
......
import os, sys, unittest ##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
import os, sys, unittest
import string, cStringIO, re import string, cStringIO, re
import ZODB, Acquisition import ZODB, Acquisition
from OFS.Application import Application from OFS.Application import Application
from OFS.Folder import manage_addFolder from OFS.Folder import manage_addFolder
from OFS.Image import manage_addFile from OFS.Image import manage_addFile
from OFS.SimpleItem import SimpleItem
from Testing.makerequest import makerequest from Testing.makerequest import makerequest
from AccessControl import SecurityManager from AccessControl import SecurityManager
from AccessControl.SecurityManagement import newSecurityManager from AccessControl.SecurityManagement import newSecurityManager
...@@ -46,6 +61,17 @@ class UnitTestUser( Acquisition.Implicit ): ...@@ -46,6 +61,17 @@ class UnitTestUser( Acquisition.Implicit ):
def allowed( self, object, object_roles=None ): def allowed( self, object, object_roles=None ):
return 1 return 1
class BoboTraversable(SimpleItem):
__allow_access_to_unprotected_subobjects__ = 1
def __bobo_traverse__(self, request, name):
if name == 'bb_subitem':
return BoboTraversable().__of__(self)
else:
raise KeyError
def makeConnection(): def makeConnection():
import ZODB import ZODB
from ZODB.DemoStorage import DemoStorage from ZODB.DemoStorage import DemoStorage
...@@ -127,6 +153,16 @@ class TestTraverse( unittest.TestCase ): ...@@ -127,6 +153,16 @@ class TestTraverse( unittest.TestCase ):
self.failUnlessRaises( KeyError, self.folder1.unrestrictedTraverse, '/folder1/file2' ) self.failUnlessRaises( KeyError, self.folder1.unrestrictedTraverse, '/folder1/file2' )
self.failUnlessRaises( KeyError, self.folder1.unrestrictedTraverse, '/folder1/file2/' ) self.failUnlessRaises( KeyError, self.folder1.unrestrictedTraverse, '/folder1/file2/' )
def testTraverseThroughBoboTraverse(self):
# Verify it's possible to use __bobo_traverse__ with the
# Zope security policy.
noSecurityManager()
SecurityManager.setSecurityPolicy( self.oldPolicy )
bb = BoboTraversable()
self.failUnlessRaises(KeyError, bb.restrictedTraverse, 'notfound')
bb.restrictedTraverse('bb_subitem')
def test_suite(): def test_suite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
suite.addTest( unittest.makeSuite( TestTraverse ) ) suite.addTest( unittest.makeSuite( TestTraverse ) )
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment