Commit 0e25715e authored by Florent Guillaume's avatar Florent Guillaume

Merged r68980 from 2.10 branch:

Fixed refactored traversal on bound methods of classes with no default
access.
parent 0500ff52
...@@ -237,11 +237,11 @@ class Traversable: ...@@ -237,11 +237,11 @@ class Traversable:
if not validated: if not validated:
raise Unauthorized, name raise Unauthorized, name
else: else:
if hasattr(aq_base(obj), name): if getattr(aq_base(obj), name, marker) is not marker:
if restricted: if restricted:
next = guarded_getattr(obj, name, marker) next = guarded_getattr(obj, name)
else: else:
next = _getattr(obj, name, marker) next = _getattr(obj, name)
else: else:
try: try:
next=obj[name] next=obj[name]
...@@ -249,6 +249,9 @@ class Traversable: ...@@ -249,6 +249,9 @@ class Traversable:
# Raise NotFound for easier debugging # Raise NotFound for easier debugging
# instead of AttributeError: __getitem__ # instead of AttributeError: __getitem__
raise NotFound, name raise NotFound, name
if restricted and not securityManager.validate(
obj, obj, _none, next):
raise Unauthorized, name
except (AttributeError, NotFound, KeyError), e: except (AttributeError, NotFound, KeyError), e:
# Try to look for a view # Try to look for a view
...@@ -274,9 +277,6 @@ class Traversable: ...@@ -274,9 +277,6 @@ class Traversable:
# Nothing found re-raise error # Nothing found re-raise error
raise e raise e
if restricted and not securityManager.validate(
obj, obj, _none, next):
raise Unauthorized, name
obj = next obj = next
return obj return obj
......
...@@ -68,6 +68,24 @@ class CruelSecurityPolicy: ...@@ -68,6 +68,24 @@ class CruelSecurityPolicy:
return 0 return 0
class ProtectedMethodSecurityPolicy:
"""Check security strictly on bound methods.
"""
def validate(self, accessed, container, name, value, *args):
if getattr(aq_base(value), 'im_self', None) is None:
return 1
# Bound method
if name is None:
raise Unauthorized
klass = value.im_self.__class__
roles = getattr(klass, name+'__roles__', object())
if roles is None: # ACCESS_PUBLIC
return 1
raise Unauthorized(name)
class UnitTestUser( Acquisition.Implicit ): class UnitTestUser( Acquisition.Implicit ):
""" """
Stubbed out manager for unit testing purposes. Stubbed out manager for unit testing purposes.
...@@ -103,6 +121,22 @@ class BoboTraversable(SimpleItem): ...@@ -103,6 +121,22 @@ class BoboTraversable(SimpleItem):
bb_status = 'screechy' bb_status = 'screechy'
class Restricted(SimpleItem):
"""Instance we'll check with ProtectedMethodSecurityPolicy
"""
getId__roles__ = None # ACCESS_PUBLIC
def getId(self):
return self.id
private__roles__ = () # ACCESS_PRIVATE
def private(self):
return 'private!'
# not protected
def ohno(self):
return 'ohno!'
class BoboTraversableWithAcquisition(SimpleItem): class BoboTraversableWithAcquisition(SimpleItem):
""" """
A BoboTraversable class which may use acquisition to find objects. A BoboTraversable class which may use acquisition to find objects.
...@@ -210,6 +244,17 @@ class TestTraverse( unittest.TestCase ): ...@@ -210,6 +244,17 @@ class TestTraverse( unittest.TestCase ):
self.failUnlessRaises( self.failUnlessRaises(
KeyError, self.folder1.unrestrictedTraverse, '/folder1/file2/' ) KeyError, self.folder1.unrestrictedTraverse, '/folder1/file2/' )
def testTraverseMethodRestricted(self):
self.root.my = Restricted('my')
my = self.root.my
my.id = 'my'
noSecurityManager()
SecurityManager.setSecurityPolicy(ProtectedMethodSecurityPolicy())
r = my.restrictedTraverse('getId')
self.assertEquals(r(), 'my')
self.assertRaises(Unauthorized, my.restrictedTraverse, 'private')
self.assertRaises(Unauthorized, my.restrictedTraverse, 'ohno')
def testBoboTraverseToWrappedSubObj(self): def testBoboTraverseToWrappedSubObj(self):
# Verify it's possible to use __bobo_traverse__ with the # Verify it's possible to use __bobo_traverse__ with the
# Zope security policy. # Zope security policy.
......
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