Commit 9cfe4e1c authored by Jérome Perrin's avatar Jérome Perrin

patches/Restricted: Fix the way we allow classes

make our type checker falseish, so that ZopeGuard security checks don't
short circuit this.
parent 25469c1d
...@@ -81,36 +81,48 @@ def allow_class_attribute(klass, access=1): ...@@ -81,36 +81,48 @@ def allow_class_attribute(klass, access=1):
assert(inspect.isclass(klass)) assert(inspect.isclass(klass))
_safe_class_attribute_dict[klass] = access _safe_class_attribute_dict[klass] = access
def _check_type_access(name, v):
class TypeAccessChecker:
"""Check Access for class instances (whose type() is `type`).
""" """
Create a method which checks the access if the context type is <type 'type'>s. def __call__(self, name, v):
"""
Create a callable which checks the access if the context type is <type 'type'>s.
Since the 'type' can be any types of classes, we support the three ways Since the 'type' can be any types of classes, we support the three ways
defined in AccessControl/SimpleObjectPolicies. We implement this defined in AccessControl/SimpleObjectPolicies. We implement this
as "a method which returing a method" because we can not know what is the as "a method which returing a method" because we can not know what is the
type until it is actually called. So the three ways are simulated the type until it is actually called. So the three ways are simulated the
returning method inide this method. function returned by this method.
"""
def factory(inst, name):
""" """
Check function used with ContainerAssetions checked by cAccessControl. def factory(inst, name):
""" """
access = _safe_class_attribute_dict.get(inst, 0) Check function used with ContainerAssertions checked by cAccessControl.
# The next 'dict' only checks the access configuration type """
if access == 1 or (isinstance(access, dict) and access.get(name, 0) == 1): access = _safe_class_attribute_dict.get(inst, 0)
pass # The next 'dict' only checks the access configuration type
elif isinstance(access, dict) and callable(access.get(name, 0)): if access == 1 or (isinstance(access, dict) and access.get(name, 0) == 1):
guarded_method = access.get(name) pass
return guarded_method(inst, name) elif isinstance(access, dict) and callable(access.get(name, 0)):
elif callable(access): guarded_method = access.get(name)
# Only check whether the access configuration raise error or not return guarded_method(inst, name)
access(inst, name) elif callable(access):
else: # Only check whether the access configuration raise error or not
# fallback to default security access(inst, name)
aq_acquire(inst, name, aq_validate, getSecurityManager().validate) else:
return v # fallback to default security
return factory aq_acquire(inst, name, aq_validate, getSecurityManager().validate)
return v
ContainerAssertions[type] = _check_type_access return factory
def __nonzero__(self):
# If Containers(type(x)) is true, ZopeGuard checks will short circuit,
# thinking it's a simple type, but we don't want this for type, because
# type(x) is type for classes, being trueish would skip security check on
# classes.
return False
ContainerAssertions[type] = TypeAccessChecker()
class SafeIterItems(SafeIter): class SafeIterItems(SafeIter):
......
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