def guard(container, value, index=None):
    if Containers(type(container)) and Containers(type(value)):
        # Simple type.  Short circuit.
        return
    if getSecurityManager().validate(container, container, index, value):
        return
    _error(index)
Exemple #2
0
def guarded_getattr(inst, name, default=_marker):
    """Retrieves an attribute, checking security in the process.

    Raises Unauthorized if the attribute is found but the user is
    not allowed to access the attribute.
    """
    if name[:1] == '_':
        raise Unauthorized, name

    # Try to get the attribute normally so that unusual
    # exceptions are caught early.
    try:
        v = getattr(inst, name)
    except AttributeError:
        if default is not _marker:
            return default
        raise

    try:
        container = v.im_self
    except AttributeError:
        container = aq_parent(aq_inner(v)) or inst

    assertion = Containers(type(container))

    if isinstance(assertion, dict):
        # We got a table that lets us reason about individual
        # attrs
        assertion = assertion.get(name)
        if assertion:
            # There's an entry, but it may be a function.
            if callable(assertion):
                return assertion(inst, name)

            # Nope, it's boolean
            return v
        raise Unauthorized, name

    if assertion:
        if callable(assertion):
            factory = assertion(name, v)
            if callable(factory):
                return factory(inst, name)
            assert factory == 1
        else:
            assert assertion == 1
        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
Exemple #3
0
def guarded_getattr(inst, name, default=_marker):
    """Retrieves an attribute, checking security in the process.

    Raises Unauthorized if the attribute is found but the user is
    not allowed to access the attribute.
    """
    if name[:1] == '_':
        raise Unauthorized, name

    # Try to get the attribute normally so that unusual
    # exceptions are caught early.
    try:
        v = getattr(inst, name)
    except AttributeError:
        if default is not _marker:
            return default
        raise

    try:
        container = v.im_self
    except AttributeError:
        container = aq_parent(aq_inner(v)) or inst

    assertion = Containers(type(container))

    if isinstance(assertion, dict):
        # We got a table that lets us reason about individual
        # attrs
        assertion = assertion.get(name)
        if assertion:
            # There's an entry, but it may be a function.
            if callable(assertion):
                return assertion(inst, name)

            # Nope, it's boolean
            return v
        raise Unauthorized, name

    if assertion:
        if callable(assertion):
            factory = assertion(name, v)
            if callable(factory):
                return factory(inst, name)
            assert factory == 1
        else:
            assert assertion == 1
        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 = getSecurityManager().validate
    aq_acquire(inst, name, aq_validate, validate)
    
    return v
Exemple #4
0
 def testContainersContextManager(self):
     from AccessControl.SimpleObjectPolicies import override_containers
     from AccessControl.SimpleObjectPolicies import ContainerAssertions
     from AccessControl.SimpleObjectPolicies import Containers
     from types import TracebackType
     # Surely we have no assertions for this type:
     self.assertNotIn(TracebackType, ContainerAssertions)
     with override_containers(TracebackType, 1):
         self.assertIn(TracebackType, ContainerAssertions)
         self.assertEqual(Containers(TracebackType), 1)
         # Override it again.
         with override_containers(TracebackType, {}):
             self.assertEqual(Containers(TracebackType), {})
         # We are outside the nested override, so the first override should
         # have been restored.
         self.assertEqual(Containers(TracebackType), 1)
     # We are outside all overrides, so the type should no longer be in the
     # assertions.
     self.assertNotIn(TracebackType, ContainerAssertions)
 def testContainersContextManager(self):
     from AccessControl.SimpleObjectPolicies import override_containers
     from AccessControl.SimpleObjectPolicies import ContainerAssertions
     from AccessControl.SimpleObjectPolicies import Containers
     from types import EllipsisType
     # Surely we have no assertions for this type.  There might be a good
     # reason to have then, but I have not even heard of this type.
     self.assertFalse(EllipsisType in ContainerAssertions)
     with override_containers(EllipsisType, 1):
         self.assertTrue(EllipsisType in ContainerAssertions)
         self.assertEqual(Containers(EllipsisType), 1)
         # Override it again.
         with override_containers(EllipsisType, {}):
             self.assertEqual(Containers(EllipsisType), {})
         # We are outside the nested override, so the first override should
         # have been restored.
         self.assertEqual(Containers(EllipsisType), 1)
     # We are outside all overrides, so the type should no longer be in the
     # assertions.
     self.assertFalse(EllipsisType in ContainerAssertions)
def guarded_getitem(object, index):
    if type(index) is SliceType:
        if index.step is not None:
            v = object[index]
        else:
            start = index.start
            stop = index.stop
            if start is None:
                start = 0
            if stop is None:
                v = object[start:]
            else:
                v = object[start:stop]
        # We don't guard slices.
        return v
    v = object[index]
    if Containers(type(object)) and Containers(type(v)):
        # Simple type.  Short circuit.
        return v
    if getSecurityManager().validate(object, object, None, v):
        return v
    raise Unauthorized('unauthorized access to element %s' % index)
    def validate(self,
                 accessed,
                 container,
                 name,
                 value,
                 context,
                 roles=_noroles,
                 getattr=getattr,
                 _noroles=_noroles,
                 valid_aq_=('aq_parent', 'aq_inner', 'aq_explicit')):

        ############################################################
        # Provide special rules for the acquisition attributes
        if isinstance(name, str):
            if name.startswith('aq_') and name not in valid_aq_:
                if self._verbose:
                    raiseVerbose(
                        'aq_* names (other than %s) are not allowed' %
                        ', '.join(valid_aq_), accessed, container, name, value,
                        context)
                raise Unauthorized(name, value)

        containerbase = aq_base(container)
        accessedbase = aq_base(accessed)
        if accessedbase is accessed:
            # accessed is not a wrapper, so assume that the
            # value could not have been acquired.
            accessedbase = container

        ############################################################
        # If roles weren't passed in, we'll try to get them from the object

        if roles is _noroles:
            roles = getRoles(container, name, value, _noroles)

        ############################################################
        # We still might not have any roles

        if roles is _noroles:

            ############################################################
            # We have an object without roles and we didn't get a list
            # of roles passed in. Presumably, the value is some simple
            # object like a string or a list.  We'll try to get roles
            # from its container.
            if container is None:
                # Either container or a list of roles is required
                # for ZopeSecurityPolicy to know whether access is
                # allowable.
                if self._verbose:
                    raiseVerbose('No container provided', accessed, container,
                                 name, value, context)
                raise Unauthorized(name, value)

            roles = getattr(container, '__roles__', roles)
            if roles is _noroles:
                if containerbase is container:
                    # Container is not wrapped.
                    if containerbase is not accessedbase:
                        if self._verbose:
                            raiseVerbose(
                                'Unable to find __roles__ in the container '
                                'and the container is not wrapped', accessed,
                                container, name, value, context)
                        raise Unauthorized(name, value)
                else:
                    # Try to acquire roles
                    try:
                        roles = aq_acquire(container, '__roles__')
                    except AttributeError:
                        if containerbase is not accessedbase:
                            if self._verbose:
                                raiseVerbose(
                                    'Unable to find or acquire __roles__ '
                                    'from the container', accessed, container,
                                    name, value, context)
                            raise Unauthorized(name, value)

            # We need to make sure that we are allowed to
            # get unprotected attributes from the container. We are
            # allowed for certain simple containers and if the
            # container says we can. Simple containers
            # may also impose name restrictions.
            p = Containers(type(container), None)
            if p is None:
                p = getattr(container,
                            '__allow_access_to_unprotected_subobjects__', None)

            if p is not None:
                if not isinstance(p, int):  # catches bool too
                    if isinstance(p, dict):
                        if isinstance(name, basestring):
                            p = p.get(name)
                        else:
                            p = 1
                    else:
                        p = p(name, value)

            if not p:
                if self._verbose:
                    raiseVerbose('The container has no security assertions',
                                 accessed, container, name, value, context)
                raise Unauthorized(name, value)

            if roles is _noroles:
                return 1

            # We are going to need a security-aware object to pass
            # to allowed(). We'll use the container.
            value = container

        # Short-circuit tests if we can:
        try:
            if roles is None or 'Anonymous' in roles:
                return 1
        except TypeError:
            # 'roles' isn't a sequence
            LOG.error("'%s' passed as roles"
                      " during validation of '%s' is not a sequence." %
                      ( ` roles `, name))
            raise

        # Check executable security
        stack = context.stack
        if stack:
            eo = stack[-1]

            # If the executable had an owner, can it execute?
            if self._ownerous:
                owner = eo.getOwner()
                if (owner is not None) and not owner.allowed(value, roles):
                    # We don't want someone to acquire if they can't
                    # get an unacquired!
                    if self._verbose:
                        if len(roles) < 1:
                            raiseVerbose("The object is marked as private",
                                         accessed, container, name, value,
                                         context)
                        elif userHasRolesButNotInContext(owner, value, roles):
                            raiseVerbose(
                                "The owner of the executing script is defined "
                                "outside the context of the object being "
                                "accessed",
                                accessed,
                                container,
                                name,
                                value,
                                context,
                                required_roles=roles,
                                eo_owner=owner,
                                eo=eo)
                        else:
                            raiseVerbose(
                                "The owner of the executing script does not "
                                "have the required permission",
                                accessed,
                                container,
                                name,
                                value,
                                context,
                                required_roles=roles,
                                eo_owner=owner,
                                eo=eo,
                                eo_owner_roles=getUserRolesInContext(
                                    owner, value))
                    raise Unauthorized(name, value)

            # Proxy roles, which are a lot safer now.
            proxy_roles = getattr(eo, '_proxy_roles', None)
            if proxy_roles:
                # Verify that the owner actually can state the proxy role
                # in the context of the accessed item; users in subfolders
                # should not be able to use proxy roles to access items
                # above their subfolder!
                owner = eo.getWrappedOwner()

                if owner is not None:
                    if container is not containerbase:
                        # Unwrapped objects don't need checking
                        if not owner._check_context(container):
                            # container is higher up than the owner,
                            # deny access
                            if self._verbose:
                                raiseVerbose(
                                    "The owner of the executing script is "
                                    "defined outside the context of the "
                                    "object being accessed.  The script has "
                                    "proxy roles, but they do not apply in "
                                    "this context.",
                                    accessed,
                                    container,
                                    name,
                                    value,
                                    context,
                                    required_roles=roles,
                                    eo_owner=owner,
                                    eo=eo)
                            raise Unauthorized(name, value)

                for r in proxy_roles:
                    if r in roles:
                        return 1

                # Proxy roles actually limit access!
                if self._verbose:
                    if len(roles) < 1:
                        raiseVerbose("The object is marked as private",
                                     accessed, container, name, value, context)
                    else:
                        raiseVerbose(
                            "The proxy roles set on the executing script "
                            "do not allow access",
                            accessed,
                            container,
                            name,
                            value,
                            context,
                            eo=eo,
                            eo_proxy_roles=proxy_roles,
                            required_roles=roles)
                raise Unauthorized(name, value)

        try:
            if self._authenticated and context.user.allowed(value, roles):
                return 1
        except AttributeError:
            pass

        if self._verbose:
            if len(roles) < 1:
                raiseVerbose("The object is marked as private", accessed,
                             container, name, value, context)
            elif not self._authenticated:
                raiseVerbose(
                    "Authenticated access is not allowed by this "
                    "security policy", accessed, container, name, value,
                    context)
            elif userHasRolesButNotInContext(context.user, value, roles):
                raiseVerbose(
                    "Your user account is defined outside "
                    "the context of the object being accessed",
                    accessed,
                    container,
                    name,
                    value,
                    context,
                    required_roles=roles,
                    user=context.user)
            else:
                raiseVerbose(
                    "Your user account does not "
                    "have the required permission",
                    accessed,
                    container,
                    name,
                    value,
                    context,
                    required_roles=roles,
                    user=context.user,
                    user_roles=getUserRolesInContext(context.user, value))
        raise Unauthorized(name, value)
    def validate(self, accessed, container, name, value, context,
                 roles=_noroles, getattr=getattr, _noroles=_noroles,
                 valid_aq_=('aq_parent', 'aq_inner', 'aq_explicit')):

        ############################################################
        # Provide special rules for the acquisition attributes
        if isinstance(name, str):
            if name.startswith('aq_') and name not in valid_aq_:
                if self._verbose:
                    raiseVerbose(
                        'aq_* names (other than %s) are not allowed'
                        % ', '.join(valid_aq_),
                        accessed,
                        container,
                        name,
                        value,
                        context,
                    )
                raise Unauthorized(name, value)

        containerbase = aq_base(container)
        accessedbase = aq_base(accessed)
        if accessedbase is accessed:
            # accessed is not a wrapper, so assume that the
            # value could not have been acquired.
            accessedbase = container

        ############################################################
        # If roles weren't passed in, we'll try to get them from the object

        if roles is _noroles:
            roles = getRoles(container, name, value, _noroles)

        ############################################################
        # We still might not have any roles

        if roles is _noroles:

            ############################################################
            # We have an object without roles and we didn't get a list
            # of roles passed in. Presumably, the value is some simple
            # object like a string or a list.  We'll try to get roles
            # from its container.
            if container is None:
                # Either container or a list of roles is required
                # for ZopeSecurityPolicy to know whether access is
                # allowable.
                if self._verbose:
                    raiseVerbose(
                        'No container provided',
                        accessed, container, name, value, context)
                raise Unauthorized(name, value)

            roles = getattr(container, '__roles__', roles)
            if roles is _noroles:
                if containerbase is container:
                    # Container is not wrapped.
                    if containerbase is not accessedbase:
                        if self._verbose:
                            raiseVerbose(
                                'Unable to find __roles__ in the container '
                                'and the container is not wrapped',
                                accessed,
                                container,
                                name,
                                value,
                                context,
                            )
                        raise Unauthorized(name, value)
                else:
                    # Try to acquire roles
                    try:
                        roles = aq_acquire(container, '__roles__')
                    except AttributeError:
                        if containerbase is not accessedbase:
                            if self._verbose:
                                raiseVerbose(
                                    'Unable to find or acquire __roles__ '
                                    'from the container',
                                    accessed, container, name, value, context)
                            raise Unauthorized(name, value)

            # We need to make sure that we are allowed to
            # get unprotected attributes from the container. We are
            # allowed for certain simple containers and if the
            # container says we can. Simple containers
            # may also impose name restrictions.
            p = Containers(type(container), None)
            if p is None:
                p = getattr(container,
                            '__allow_access_to_unprotected_subobjects__',
                            None)

            if p is not None:
                if not isinstance(p, (bool, int)):
                    if isinstance(p, dict):

                        if isinstance(name, string_types):
                            p = p.get(name)
                        else:
                            p = 1
                    else:
                        p = p(name, value)

            if not p:
                if self._verbose:
                    raiseVerbose(
                        'The container has no security assertions',
                        accessed,
                        container,
                        name,
                        value,
                        context,
                    )
                raise Unauthorized(name, value)

            if roles is _noroles:
                return 1

            # We are going to need a security-aware object to pass
            # to allowed(). We'll use the container.
            value = container

        # Short-circuit tests if we can:
        try:
            if roles is None or 'Anonymous' in roles:
                return 1
        except TypeError:
            # 'roles' isn't a sequence
            LOG.error(
                "'%r' passed as roles"
                " during validation of '%s' is not a sequence." % (
                    roles,
                    name,
                ),
            )
            raise

        # Check executable security
        stack = context.stack
        if stack:
            eo = stack[-1]

            # If the executable had an owner, can it execute?
            if self._ownerous:
                owner = eo.getOwner()
                if (owner is not None) and not owner.allowed(value, roles):
                    # We don't want someone to acquire if they can't
                    # get an unacquired!
                    if self._verbose:
                        if len(roles) < 1:
                            raiseVerbose(
                                "The object is marked as private",
                                accessed,
                                container,
                                name,
                                value,
                                context,
                            )
                        elif userHasRolesButNotInContext(owner, value, roles):
                            raiseVerbose(
                                "The owner of the executing script is defined "
                                "outside the context of the object being "
                                "accessed",
                                accessed,
                                container,
                                name,
                                value,
                                context,
                                required_roles=roles,
                                eo_owner=owner,
                                eo=eo,
                            )
                        else:
                            raiseVerbose(
                                "The owner of the executing script does not "
                                "have the required permission",
                                accessed,
                                container,
                                name,
                                value,
                                context,
                                required_roles=roles,
                                eo_owner=owner,
                                eo=eo,
                                eo_owner_roles=getUserRolesInContext(owner,
                                                                     value),
                            )
                    raise Unauthorized(name, value)

            # Proxy roles, which are a lot safer now.
            proxy_roles = getattr(eo, '_proxy_roles', None)
            if proxy_roles:
                # Verify that the owner actually can state the proxy role
                # in the context of the accessed item; users in subfolders
                # should not be able to use proxy roles to access items
                # above their subfolder!
                owner = eo.getWrappedOwner()

                if owner is not None:
                    if container is not containerbase:
                        # Unwrapped objects don't need checking
                        if not owner._check_context(container):
                            # container is higher up than the owner,
                            # deny access
                            if self._verbose:
                                raiseVerbose(
                                    "The owner of the executing script is "
                                    "defined outside the context of the "
                                    "object being accessed.  The script has "
                                    "proxy roles, but they do not apply in "
                                    "this context.",
                                    accessed, container, name, value, context,
                                    required_roles=roles, eo_owner=owner,
                                    eo=eo)
                            raise Unauthorized(name, value)

                for r in proxy_roles:
                    if r in roles:
                        return 1

                # Proxy roles actually limit access!
                if self._verbose:
                    if len(roles) < 1:
                        raiseVerbose(
                            "The object is marked as private",
                            accessed, container, name, value, context)
                    else:
                        raiseVerbose(
                            "The proxy roles set on the executing script "
                            "do not allow access",
                            accessed, container, name, value, context,
                            eo=eo, eo_proxy_roles=proxy_roles,
                            required_roles=roles)
                raise Unauthorized(name, value)

        try:
            if self._authenticated and context.user.allowed(value, roles):
                return 1
        except AttributeError:
            pass

        if self._verbose:
            if len(roles) < 1:
                raiseVerbose(
                    "The object is marked as private",
                    accessed, container, name, value, context)
            elif not self._authenticated:
                raiseVerbose(
                    "Authenticated access is not allowed by this "
                    "security policy",
                    accessed, container, name, value, context)
            elif userHasRolesButNotInContext(context.user, value, roles):
                raiseVerbose(
                    "Your user account is defined outside "
                    "the context of the object being accessed",
                    accessed, container, name, value, context,
                    required_roles=roles, user=context.user)
            else:
                raiseVerbose(
                    "Your user account does not "
                    "have the required permission",
                    accessed, container, name, value, context,
                    required_roles=roles, user=context.user,
                    user_roles=getUserRolesInContext(context.user, value))
        raise Unauthorized(name, value)