[Zope-Checkins] CVS: Zope/lib/python/AccessControl - SimpleObjectPolicies.py:1.12.6.2 ZopeGuards.py:1.12.4.6 cAccessControl.c:1.17.6.5

Jim Fulton jim at zope.com
Mon Jan 19 13:54:41 EST 2004


Update of /cvs-repository/Zope/lib/python/AccessControl
In directory cvs.zope.org:/tmp/cvs-serv4014/lib/python/AccessControl

Modified Files:
      Tag: Zope-2_6-branch
	SimpleObjectPolicies.py ZopeGuards.py cAccessControl.c 
Log Message:
Collector #1182: Functions for handling decisions about
unprotected subobjects were not passed "names" when doing
unnamed (item) access.  In 2.6.3 we changed access checks when
doing item access to pass None rather than the key value when
validating access. This broke some existing applications.  We
have reverted these changes.


=== Zope/lib/python/AccessControl/SimpleObjectPolicies.py 1.12.6.1 => 1.12.6.2 ===
--- Zope/lib/python/AccessControl/SimpleObjectPolicies.py:1.12.6.1	Thu Jan  8 15:12:07 2004
+++ Zope/lib/python/AccessControl/SimpleObjectPolicies.py	Mon Jan 19 13:54:10 2004
@@ -10,40 +10,33 @@
 # FOR A PARTICULAR PURPOSE
 #
 ##############################################################################
-"""Collect rules for access to objects that don\'t have roles.
+"""Collect some policies for s few built-in container objects.
 
-An assertion can be:
+   This module defines a registry, ContainerAssertions, that contains
+   some data that is used by the zope security policy and by zope
+   guards when considering whether to allow access to objects.
 
-  - A dict
+   The zope security policy and the zope guards use this data in
+   different ways.  The source code for those modules is the best
+   source of documentation for their use. :(
 
-  - A callable
+   The requirements for the values of ContainerAssertions is provided
+   here.
 
-  - Something with a truth value
+   The keys of ContainerAssertions are built-in types.
 
-If the assertion is a callable, then it will be called with
-a name being accessed and the name used.  Its return value is ignored,
-but in may veto an access by raising an exception.
+   The values must be one of:
 
-N.B.:  ExtensionClass instances *always* look callable;  hence, unless you
-       really designed your EC-derived instance to be called to perform
-       checked access to a container's method, *don't* use it as a
-       container assertion.
+   1 -- In this case access to attributes of instances of the type are
+        always allowed.  Access to items may be allowed, depending on
+        the item type and value. (Use the source.)
 
-If the assertion is a dictionary, then the keys are attribute names.
-The values may be callables or objects with boolean values. If a value
-is callable, it will be called with the object we are accessing an
-attribute of and the attribute name. It should return an attribute
-value. Callables are often used to returned guarded versions of
-methods.  Otherwise, accesses are allowed if values in this dictionary
-are true and disallowed if the values are false or if an item for an
-attribute name is not present.
-
-If the assertion is not a dict and is not callable, then access to
-unprotected attributes is allowed if the assertion is true, and
-disallowed otherwise.
-
-XXX This descrition doesn't actually match what's done in ZopeGuards
-or in ZopeSecurityPolicy. :(
+   a callable -- In this case, the callable will be called with the
+        attribute name and value and should return a true callable or
+        1. If 1 is returned, then access may be granted, otherwise the
+        second callable will be called with the original object, and
+        the attribute name, and should return an object that is
+        returned as the value of the attribute.
 
 $Id$
 """


=== Zope/lib/python/AccessControl/ZopeGuards.py 1.12.4.5 => 1.12.4.6 ===
--- Zope/lib/python/AccessControl/ZopeGuards.py:1.12.4.5	Fri Jan 16 13:12:43 2004
+++ Zope/lib/python/AccessControl/ZopeGuards.py	Mon Jan 19 13:54:10 2004
@@ -31,6 +31,46 @@
 RP_safe_builtins, safe_builtins = safe_builtins, safe_builtins.copy()
 safe_builtins.update(utility_builtins)
 
+# This is always created do that we can test it independently of whether
+# we are using the C version.
+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] != '_':
+        # 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
+
+        assertion = Containers(type(inst))
+        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
+
+        validate = getSecurityManager().validate
+        # Filter out the objects we can't access.
+        if hasattr(inst, 'aq_acquire'):
+            return inst.aq_acquire(name, aq_validate, validate)
+        # Or just try to get the attribute directly.
+        if validate(inst, inst, name, v):
+            return v
+    raise Unauthorized, name
+
+guarded_getattr_py = guarded_getattr
+
 try:
 
     #raise ImportError
@@ -44,48 +84,6 @@
     def aq_validate(inst, obj, name, v, validate):
         return validate(inst, obj, name, v)
 
-
-    def guarded_getattr(inst, name, default=_marker):
-        if name[:1] != '_':
-            # 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
-
-            assertion = Containers(type(inst))
-            if type(assertion) is DictType:
-                # 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
-            
-            elif assertion:
-                # So the entry in the outer table is not a dict 
-                # It's allowed to be a vetoing function:
-                if callable(assertion):
-                    assertion(name, v)
-                # No veto, so we can return
-                return v
-                
-            validate = getSecurityManager().validate
-            # Filter out the objects we can't access.
-            if hasattr(inst, 'aq_acquire'):
-                return inst.aq_acquire(name, aq_validate, validate)
-            # Or just try to get the attribute directly.
-            if validate(inst, inst, name, v):
-                return v
-        raise Unauthorized, name
-
 safe_builtins['getattr'] = guarded_getattr
 
 def guarded_hasattr(object, name):
@@ -115,7 +113,7 @@
     if Containers(type(object)) and Containers(type(v)):
         # Simple type.  Short circuit.
         return v
-    if getSecurityManager().validate(object, object, None, v):
+    if getSecurityManager().validate(object, object, index, v):
         return v
     raise Unauthorized, 'unauthorized access to element %s' % `i`
 
@@ -155,15 +153,23 @@
         return v        
     return guarded_pop
 
-ContainerAssertions[DictType] = {
-    'clear':1, 'copy':1, 'fromkeys':1, 'get':get_dict_get, 'has_key':1,
-    'items':1, 'iteritems':1, 'keys':1, 
+
+# Provide special handling for some dict and list methods.
+
+dict_handlers = {
+    'get':get_dict_get, 'has_key':1,
     'iterkeys': get_iter,  'itervalues':get_iter,
-    'pop':get_dict_pop, 'popitem':1, 'setdefault':1, 'update':1, 'values':1}
+    'pop':get_dict_pop, }
+def dict_attr_factory(attr, v, handlers = dict_handlers):
+    return handlers.get(attr, 1)
+
+ContainerAssertions[type({})] = dict_attr_factory
+
+list_handlers = {'pop':get_list_pop, }
+def list_attr_factory(attr, v, handlers = list_handlers):
+    return handlers.get(attr, 1)
 
-ContainerAssertions[ListType] = {
-    'append':1, 'count':1, 'extend':1, 'index':1, 'insert':1, 
-    'pop':get_list_pop, 'remove':1, 'reverse':1, 'sort':1}
+ContainerAssertions[type([])] = list_attr_factory
 
 # This implementation of a "safe" iterator uses a global guard()
 # function to implement the actual guard.  This check is defined as a


=== Zope/lib/python/AccessControl/cAccessControl.c 1.17.6.4 => 1.17.6.5 ===
--- Zope/lib/python/AccessControl/cAccessControl.c:1.17.6.4	Wed Jan 14 13:58:47 2004
+++ Zope/lib/python/AccessControl/cAccessControl.c	Mon Jan 19 13:54:10 2004
@@ -2127,73 +2127,37 @@
         }
 
       /*
-            assertion = Containers(type(inst))
-            if type(assertion) is DictType:
-                # 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
-            
-            elif assertion:
-                # So the entry in the outer table is not a dict 
-                # It's allowed to be a vetoing function:
-                if callable(assertion):
-                    assertion(name, v)
-                # No veto, so we can return
-                return v
+
+        assertion = Containers(type(inst))
+        if assertion:
+            if callable(assertion):
+                factory = assertion(name, v)
+                if callable(factory):
+                    return factory(inst, name)
+                assert factory == 1
+            assert callable == 1
+            return v
+
       */
       t = PyDict_GetItem(ContainerAssertions, OBJECT(inst->ob_type));
       if (t != NULL)
         {
-          if (PyDict_Check(t))
-            {
-              PyObject *attrv;
-              
-              attrv = PyDict_GetItem(t, name);
-              if (attrv != NULL)
-                {
-                  i=PyObject_IsTrue(attrv);
-                  if (i < 0) goto err;
-                  if (i) 
-                    {
-                      if (PyCallable_Check(attrv))
-                        {
-                          Py_DECREF(v);
-                          v = callfunction2(attrv, inst, name);
-                          return v;
-                        }
-                      return v;
-                    }
-                }
-              Py_DECREF(v);
-              goto unauth;
-            }
-          
-          i = PyObject_IsTrue(t);
-          if (i < 0) goto err;
-          if (i)
+          if (PyCallable_Check(t))
             {
-              if (t->ob_type->tp_call)
+              PyObject *factory;
+
+              factory = callfunction2(t, name, v);
+              if (factory == NULL) 
+                goto err;
+
+              if (PyCallable_Check(factory))
                 {
-                  PyObject *ignored;
-                  ignored = callfunction2(t, name, v);
-                  if (ignored == NULL)
-                    {
-                      /* veto */
-                      Py_DECREF(v);
-                      return NULL;
-                    }
-                  Py_DECREF(ignored);
+                  Py_DECREF(v);
+                  v = callfunction2(factory, inst, name);
                 }
-              return v;
+              Py_DECREF(factory);
             }
+          return v;
         }
 
       /*
@@ -2225,7 +2189,6 @@
       return NULL;
     }
 
- unauth:
   /* raise Unauthorized, name */
   PyErr_SetObject(Unauthorized, name);
   return NULL;




More information about the Zope-Checkins mailing list