[Zope-CVS] CVS: Products/VerboseSecurity - CHANGES.txt:1.4 PermissionRolePatch.py:1.4 README.txt:1.3 VerboseSecurityPolicy.py:1.7 __init__.py:1.3 version.txt:1.5

Shane Hathaway shane at zope.com
Wed Jun 16 22:38:48 EDT 2004


Update of /cvs-repository/Products/VerboseSecurity
In directory cvs.zope.org:/tmp/cvs-serv20441

Modified Files:
	CHANGES.txt PermissionRolePatch.py README.txt 
	VerboseSecurityPolicy.py __init__.py version.txt 
Log Message:
Version 0.6, which requires Zope 2.7.


=== Products/VerboseSecurity/CHANGES.txt 1.3 => 1.4 ===
--- Products/VerboseSecurity/CHANGES.txt:1.3	Thu Jan  8 10:39:50 2004
+++ Products/VerboseSecurity/CHANGES.txt	Wed Jun 16 22:38:44 2004
@@ -1,10 +1,16 @@
 
-Next release:
+Version 0.6:
 
-    - When run under Zope 2.7, the verbose policy now behaves the same
-      way Zope 2.7's policy behaves.  Specifically, the "accessed"
-      argument is now ignored and any denial of access raises an
-      exception rather than returning 0.
+    - This version is compatible only with Zope 2.7.  Zope's security
+      machinery changed enough that compatibility with earlier versions
+      of Zope is too difficult to maintain.
+
+    - VerboseSecurity no longer requires the Python security
+      implementation to show what permission was required.  It is now
+      possible to monkey-patch the C code!
+
+    - It is now possible to disable verbose security with an
+      environment variable.  See __init__.py.
 
 Version 0.5:
 


=== Products/VerboseSecurity/PermissionRolePatch.py 1.3 => 1.4 ===
--- Products/VerboseSecurity/PermissionRolePatch.py:1.3	Tue Feb  3 15:35:41 2004
+++ Products/VerboseSecurity/PermissionRolePatch.py	Wed Jun 16 22:38:44 2004
@@ -1,14 +1,13 @@
 ##############################################################################
 #
-# Copyright (c) 2002 Zope Corporation and Contributors.
-# All Rights Reserved.
+# Copyright (c) 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
+# FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
 __doc__="""Patch of PermissionRole.
@@ -18,76 +17,102 @@
 $Id$
 """
 
+import sys
+from ExtensionClass import Base
 from AccessControl.PermissionRole \
-     import _what_not_even_god_should_do, imPermissionRole
+     import PermissionRole, _what_not_even_god_should_do
+from zLOG import LOG, ERROR
 
-__reload_module__ = 0
 
+try:
+    # Patch PermissionRole.
 
-if 1:
-
-    if imPermissionRole.__module__ in (
-        'AccessControl.PermissionRole',  # Before Zope 2.7
-        'AccessControl.ImplPython',  # Zope 2.7
-        ):
-        # Patch only the Python implementation
-        from types import StringType, UnicodeType
-
-        def __of__(self, parent):
-            obj=parent
-            n=self._p
-            # The next line includes the permission name
-            # in the allowable roles.
-            r = [n]
-            while 1:
-                if hasattr(obj,n):
-                    roles=getattr(obj, n)
-
-                    if roles is None: return 'Anonymous',
-
-                    t=type(roles)
-
-                    if t is type(()):
-                        # If we get a tuple, then we don't acquire
-                        if r is None: return roles
-                        return r+list(roles)
-
-                    if issubclass(t, StringType) or issubclass(t, UnicodeType):
-                        # We found roles set to a name.  Start over
-                        # with the new permission name.  If the permission
-                        # name is '', then treat as private!
-                        if roles:
-                            if roles != n:
-                                n=roles
-                            # If we find a name that is the same as the
-                            # current name, we just ignore it.
-                            roles=None
-                        else:
-                            return _what_not_even_god_should_do
-
-                    elif roles:
-                        if r is None: r=list(roles)
-                        else: r=r+list(roles)
-
-                obj=getattr(obj, 'aq_inner', None)
-                if obj is None: break
-                obj=obj.aq_parent
-
-            if r is None or len(r) < 2:
-                r = self._d
-
+    def __of__(self, parent):
+        r = imPermissionRole()
+        r._p = self._p
+        r._pa = parent
+        r._d = self._d
+        p = getattr(parent, 'aq_inner', None)
+        if p is not None:
+            return r.__of__(p)
+        else:
             return r
 
-        imPermissionRole.__of__ = __of__
+    PermissionRole.__of__ = __of__
 
-    else:
+except:
+    LOG('VerboseSecurity', ERROR, "Unable to patch PermissionRole.",
+        error=sys.exc_info())
+
+
+class imPermissionRole(Base):
+    """Implement permission-based roles"""
+
+    def __of__(self, parent):
+        obj = parent
+        n = self._p
+        # The next line includes the permission name
+        # in the allowable roles.
+        r = [n]
+        while 1:
+            if hasattr(obj, n):
+                roles = getattr(obj, n)
+
+                if roles is None:
+                    return 'Anonymous',
+
+                t = roles.__class__
+
+                if t is tuple:
+                    # If we get a tuple, then we don't acquire
+                    if r is None:
+                        return roles
+                    return r + list(roles)
+
+                if issubclass(t, basestring):
+                    # We found roles set to a name.  Start over
+                    # with the new permission name.  If the permission
+                    # name is '', then treat as private!
+                    if roles:
+                        if roles != n:
+                            n = roles
+                        # If we find a name that is the same as the
+                        # current name, we just ignore it.
+                        roles = None
+                    else:
+                        return _what_not_even_god_should_do
+
+                elif roles:
+                    if r is None: r = list(roles)
+                    else: r = r + list(roles)
+
+            obj = getattr(obj, 'aq_inner', None)
+            if obj is None:
+                break
+            obj = obj.aq_parent
+
+        if r is None or len(r) < 2:
+            r = self._d
+
+        return r
+
+    # The following methods are needed in the unlikely case that an unwrapped
+    # object is accessed:
+    def __getitem__(self, i):
+        try:
+            v = self._v
+        except:
+            v = self._v = self.__of__(self._pa)
+            del self._pa
+
+        return v[i]
+
+    def __len__(self):
+        try:
+            v = self._v
+        except:
+            v = self._v = self.__of__(self._pa)
+            del self._pa
+
+        return len(v)
 
-        from zLOG import LOG, INFO
-        from App.version_txt import getZopeVersion
-        pre_2_7 = (tuple(getZopeVersion()[:2]) < (2, 7))
-        if pre_2_7:
-            msg = "put ZOPE_SECURITY_POLICY=PYTHON in the environment."
-        else:
-            msg = "add 'security-policy-implementation python' to zope.conf."
-        LOG('VerboseSecurity', INFO, "Unable to patch PermissionRole. "
-            "To see permission names in Unauthorized exceptions, " + msg)


=== Products/VerboseSecurity/README.txt 1.2 => 1.3 ===
--- Products/VerboseSecurity/README.txt:1.2	Thu Aug 22 13:26:31 2002
+++ Products/VerboseSecurity/README.txt	Wed Jun 16 22:38:44 2004
@@ -29,8 +29,7 @@
 roles, and other pertinent information.  All of this information
 appears in the exception message when access is denied.
 
-This product is designed for Zope 2.6.  However, it should work with
-Zope 2.4 and Zope 2.5 as well.  It is currently in development.
+The current version of this product is designed for Zope 2.7.
 
 
 Installation
@@ -40,30 +39,12 @@
 product replaces the Zope security policy with the
 "VerboseSecurityPolicy".
 
-This product can only show permission names if it is able to
-dynamically patch (or "monkey-patch") the Python version of the Zope
-PermissionRole module.  Everything else works without the patch, but
-the required permission name is probably the most useful piece of
-information that VerboseSecurity exposes.
-
-Zope 2.5 and 2.6 include a C version of the PermissionRole module.
-This product can not dynamically patch the C version.  So to enable
-the display of permission names, you need to get Zope to use the
-Python version of the PermissionRole module.  Do this by putting the
-following in your environment before starting Zope::
-
-    ZOPE_SECURITY_POLICY=PYTHON
-
-If you start Zope with the VerboseSecurity product installed but with
-the C version of PermissionRole, VerboseSecurity will issue a warning in
-the Zope log file.
-
 The next time an Unauthorized exception occurs, you'll get a complete
-explanation for the failed access.  If you're using Zope 2.6, you can
-also see recent exceptions through the web using the error_log object.
-Note, however, that in the default configuration, error_log will not
-display Unauthorized exceptions.  Just remove "Unauthorized" from the
-list of ignored exceptions.
+explanation for the failed access.  You can also see recent exceptions
+through the web using the error_log object.  Note, however, that in
+the default configuration, error_log will not display Unauthorized
+exceptions.  Just remove "Unauthorized" from the list of ignored
+exceptions.
 
 
 Side effects
@@ -80,11 +61,6 @@
 site, so it may not be appropriate for some production sites.  It is
 unlikely to inadvertently reveal passwords, though.
 
-- The product may sometimes append information about a previous
-Unauthorized exception to a new, unrelated Unauthorized exception.
-Zope makes it difficult to do the right thing here, but possible
-solutions exist.
-
 - The PermissionRole patch included in the product internally adds an
 imaginary role to the roles computed for a permission.  The imaginary
 role is a munged version of the permission name.  Consequently, it is
@@ -93,5 +69,3 @@
 assignment and assign users directly to permissions.  But this feature
 should not be regarded as standard, and it is not officially
 supported.
-
-


=== Products/VerboseSecurity/VerboseSecurityPolicy.py 1.6 => 1.7 ===
--- Products/VerboseSecurity/VerboseSecurityPolicy.py:1.6	Thu Jan  8 10:39:50 2004
+++ Products/VerboseSecurity/VerboseSecurityPolicy.py	Wed Jun 16 22:38:44 2004
@@ -7,7 +7,7 @@
 # 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
+# FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
 __doc__="""Verbose version of Zope security policy
@@ -17,267 +17,268 @@
 __version__='$Revision$'[11:-2]
 
 
-if 1:  # Preserve indentation for better diff
+from Acquisition import aq_base, aq_inner, aq_parent
+from AccessControl import Unauthorized
+from AccessControl.SimpleObjectPolicies import Containers, _noroles
+from zLOG import LOG, PROBLEM, BLATHER
+
+from AccessControl.PermissionRole import _what_not_even_god_should_do, \
+     rolesForPermissionOn
+
+
+class VerboseSecurityPolicy:
+
+    def __init__(self, ownerous=1, authenticated=1):
+        """Create a Zope security policy.
+
+        Two optional keyword arguments may be provided:
+
+        ownerous -- Untrusted users can create code
+                    (e.g. Python scripts or templates),
+                    so check that code owners can access resources.
+                    The argument must have a truth value.
+                    The default is true.
+
+        authenticated -- Allow access to resources based on the
+                    privaledges of the authenticated user.
+                    The argument must have a truth value.
+                    The default is true.
+
+                    This (somewhat experimental) option can be set
+                    to false on sites that allow only public
+                    (unauthenticated) access. An anticipated
+                    scenario is a ZEO configuration in which some
+                    clients allow only public access and other
+                    clients allow full management.
+        """
+        self._ownerous = ownerous
+        self._authenticated = authenticated
+
+    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_:
+                info = setUnauthorized(
+                    'aq_* names (other than %s) are not allowed'
+                    % ', '.join(valid_aq_),
+                    accessed, container, name, value, context)
+                raise Unauthorized(info)
 
-    from types import StringType, IntType, DictType, UnicodeType
+        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
 
-    from AccessControl import SimpleObjectPolicies
-    from AccessControl import Unauthorized
-    try:
-        _noroles = SimpleObjectPolicies._noroles
-    except AttributeError:
-        _noroles = []
-    Containers = SimpleObjectPolicies.Containers
-    from zLOG import LOG, PROBLEM, BLATHER
-    from Acquisition import aq_base, aq_inner, aq_parent
-
-    from AccessControl.PermissionRole import _what_not_even_god_should_do, \
-         rolesForPermissionOn
-
-    from App.version_txt import getZopeVersion
-    pre_2_7 = (tuple(getZopeVersion()[:2]) < (2, 7))
-
-
-    class VerboseSecurityPolicy:
-
-        def __init__(self, ownerous=1, authenticated=1):
-            """Create a Zope security policy.
-
-            Two optional keyword arguments may be provided:
-
-            ownerous -- Untrusted users can create code
-                        (e.g. Python scripts or templates),
-                        so check that code owners can access resources.
-                        The argument must have a truth value.
-                        The default is true.
-
-            authenticated -- Allow access to resources based on the
-                        privaledges of the authenticated user.
-                        The argument must have a truth value.
-                        The default is true.
-
-                        This (somewhat experimental) option can be set
-                        to false on sites that allow only public
-                        (unauthenticated) access. An anticipated
-                        scenario is a ZEO configuration in which some
-                        clients allow only public access and other
-                        clients allow full management.
-            """
-
-            self._ownerous=ownerous
-            self._authenticated=authenticated
-
-        def validate(self, accessed, container, name, value, context,
-                     roles=_noroles, _noroles=_noroles,
-                     valid_aq_=('aq_parent','aq_inner', 'aq_explicit')):
+        ############################################################
+        # If roles weren't passed in, we'll try to get them from the object
 
+        if roles is _noroles:
+            roles = getattr(value, '__roles__', roles)
 
-            ############################################################
-            # Provide special rules for the acquisition attributes
-            if type(name) is StringType:
-                if name.startswith('aq_') and name not in valid_aq_:
-                    setUnauthorized('aq_* names are not allowed',
-                                    accessed, container, name, value, context)
-                    return 0
-
-            containerbase = aq_base(container)
-            if pre_2_7:
-                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
-            # else the "accessed" argument is not used.
+        ############################################################
+        # We still might not have any roles
 
-            ############################################################
-            # If roles weren't passed in, we'll try to get them from the object
-
-            if roles is _noroles:
-                roles=getattr(value, '__roles__', _noroles)
+        if roles is _noroles:
 
             ############################################################
-            # We still might not have any roles
+            # 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.
+                info = setUnauthorized(
+                    'No container provided',
+                    accessed, container, name, value, context)
+                raise Unauthorized(info)
 
+            roles = getattr(container, '__roles__', 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:
-                    info = setUnauthorized(
-                        'No container provided',
-                        accessed, container, name, value, context)
-                    if pre_2_7:
-                        return 0 # Bail if no container
-                    raise Unauthorized(info)
-
-                roles=getattr(container, '__roles__', _noroles)
-                if roles is _noroles:
-                    if containerbase is container:
-                        # container is not wrapped.
-                        if pre_2_7 and containerbase is not accessedbase:
-                            setUnauthorized(
-                                'Unable to find __roles__ in the container '
-                                'and the container is not wrapped',
-                                accessed, container, name, value, context)
-                            return 0
-                    else:
-                        # Try to acquire roles
-                        try: roles = container.aq_acquire('__roles__')
-                        except AttributeError:
-                            if pre_2_7 and containerbase is not accessedbase:
-                                setUnauthorized(
-                                    'Unable to find or acquire __roles__ '
-                                    'from the container',
-                                    accessed, container, name, value, context)
-                                return 0
-
-                # 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:
-                    tp=type(p)
-                    if tp is not IntType:
-                        if tp is DictType:
-                            if (isinstance(name, UnicodeType) or
-                                isinstance(name, StringType)):
-                                p = p.get(name)
-                            else:
-                                p = 1
-                        else:
-                            p=p(name, value)
-
-                if not p:
-                    info = setUnauthorized(
-                        'The container has no security assertions',
-                        accessed, container, name, value, context
-                        )
-                    if pre_2_7 and containerbase is not accessedbase:
-                        return 0
-                    raise Unauthorized(info)
-
-                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('Zope Security Policy', PROBLEM, "'%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 len(roles) < 1:
+                if containerbase is container:
+                    # Container is not wrapped.
+                    if containerbase is not accessedbase:
+                        info = setUnauthorized(
+                            'Unable to find __roles__ in the container '
+                            'and the container is not wrapped',
+                            accessed, container, name, value, context)
+                        raise Unauthorized(info)
+                else:
+                    # Try to acquire roles
+                    try: roles = container.aq_acquire('__roles__')
+                    except AttributeError:
+                        if containerbase is not accessedbase:
                             info = setUnauthorized(
-                                "The object is marked as private",
+                                'Unable to find or acquire __roles__ '
+                                'from the container',
                                 accessed, container, name, value, context)
-                        elif userHasRolesButNotInContext(owner, value, roles):
-                            info = setUnauthorized(
-                                "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)
+                            raise Unauthorized(info)
+
+            # 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:
+                tp = p.__class__
+                if tp is not int:
+                    if tp is dict:
+                        if isinstance(name, basestring):
+                            p = p.get(name)
                         else:
-                            info = setUnauthorized(
-                                "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))
-                        if pre_2_7 and containerbase is not accessedbase:
-                            return 0
-                        raise Unauthorized(info)
+                            p = 1
+                    else:
+                        p = p(name, value)
 
-                # Proxy roles, which are a lot safer now.
-                proxy_roles=getattr(eo, '_proxy_roles', None)
-                if proxy_roles:
-                    for r in proxy_roles:
-                        if r in roles: return 1
+            if not p:
+                info = setUnauthorized(
+                    'The container has no security assertions',
+                    accessed, container, name, value, context
+                    )
+                raise Unauthorized(info)
+
+            if roles is _noroles:
+                return 1
 
-                    # Proxy roles actually limit access!
+            # 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('Zope Security Policy', PROBLEM, "'%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 len(roles) < 1:
                         info = setUnauthorized(
                             "The object is marked as private",
                             accessed, container, name, value, context)
+                    elif userHasRolesButNotInContext(owner, value, roles):
+                        info = setUnauthorized(
+                            "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:
                         info = setUnauthorized(
-                            "The proxy roles set on the executing script "
-                            "do not allow access",
+                            "The owner of the executing script does not "
+                            "have the required permission",
                             accessed, container, name, value, context,
-                            eo=eo, eo_proxy_roles=proxy_roles,
-                            required_roles=roles)
-                    if pre_2_7 and containerbase is not accessedbase:
-                        return 0
+                            required_roles=roles, eo_owner=owner, eo=eo,
+                            eo_owner_roles=getUserRolesInContext(
+                            owner, value))
                     raise Unauthorized(info)
 
+            # 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
+                            info = setUnauthorized(
+                                "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(info)
 
-            try:
-                if self._authenticated and context.user.allowed(value, roles):
-                    return 1
-            except AttributeError: pass
+                for r in proxy_roles:
+                    if r in roles:
+                        return 1
 
-            # We don't want someone to acquire if they can't get an unacquired!
-            if len(roles) < 1:
-                info = setUnauthorized(
-                    "The object is marked as private",
-                    accessed, container, name, value, context)
-            elif not self._authenticated:
-                info = setUnauthorized(
-                    "Authenticated access is not allowed by this "
-                    "security policy",
-                    accessed, container, name, value, context)
-            elif userHasRolesButNotInContext(context.user, value, roles):
-                info = setUnauthorized(
-                    "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:
-                info = setUnauthorized(
-                    "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))
-            if pre_2_7 and containerbase is not accessedbase:
-                return 0
-            raise Unauthorized(info)
-
-
-        def checkPermission(self, permission, object, context):
-            # XXX proxy roles and executable owner are not checked
-            roles=rolesForPermissionOn(permission, object)
-            if isinstance(roles, StringType) or isinstance(roles, UnicodeType):
-                roles=[roles]
-            return context.user.allowed(object, roles)
+                # Proxy roles actually limit access!
+                if len(roles) < 1:
+                    info = setUnauthorized(
+                        "The object is marked as private",
+                        accessed, container, name, value, context)
+                else:
+                    info = setUnauthorized(
+                        "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(info)
+
+        try:
+            if self._authenticated and context.user.allowed(value, roles):
+                return 1
+        except AttributeError:
+            pass
+
+        if len(roles) < 1:
+            info = setUnauthorized(
+                "The object is marked as private",
+                accessed, container, name, value, context)
+        elif not self._authenticated:
+            info = setUnauthorized(
+                "Authenticated access is not allowed by this "
+                "security policy",
+                accessed, container, name, value, context)
+        elif userHasRolesButNotInContext(context.user, value, roles):
+            info = setUnauthorized(
+                "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:
+            info = setUnauthorized(
+                "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(info)
+
+
+    def checkPermission(self, permission, object, context):
+        # XXX proxy roles and executable owner are not checked
+        roles = rolesForPermissionOn(permission, object)
+        if isinstance(roles, basestring):
+            roles = [roles]
+        return context.user.allowed(object, roles)
 
 
 def item_repr(ob):


=== Products/VerboseSecurity/__init__.py 1.2 => 1.3 ===
--- Products/VerboseSecurity/__init__.py:1.2	Fri Aug 30 11:21:39 2002
+++ Products/VerboseSecurity/__init__.py	Wed Jun 16 22:38:44 2004
@@ -16,8 +16,10 @@
 $Id$
 """
 
+import os
 from VerboseSecurityPolicy import VerboseSecurityPolicy
-from AccessControl.SecurityManager import setSecurityPolicy
-setSecurityPolicy(VerboseSecurityPolicy())
 
-import PermissionRolePatch
+if os.environ.get('ZOPE_VERBOSE_SECURITY', '1'):
+    from AccessControl.SecurityManager import setSecurityPolicy
+    setSecurityPolicy(VerboseSecurityPolicy())
+    import PermissionRolePatch


=== Products/VerboseSecurity/version.txt 1.4 => 1.5 ===
--- Products/VerboseSecurity/version.txt:1.4	Thu Jan  8 10:39:50 2004
+++ Products/VerboseSecurity/version.txt	Wed Jun 16 22:38:44 2004
@@ -1 +1 @@
-VerboseSecurity-0.5+
+VerboseSecurity-0.6




More information about the Zope-CVS mailing list