[Zope-Checkins] CVS: Zope/lib/python/AccessControl - cAccessControl.c:1.24

Brian Lloyd brian at zope.com
Wed Jan 14 14:03:54 EST 2004


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

Modified Files:
	cAccessControl.c 
Log Message:
sync 2.7 cAccessControl


=== Zope/lib/python/AccessControl/cAccessControl.c 1.23 => 1.24 ===
--- Zope/lib/python/AccessControl/cAccessControl.c:1.23	Fri Nov 28 11:44:12 2003
+++ Zope/lib/python/AccessControl/cAccessControl.c	Wed Jan 14 14:03:53 2004
@@ -354,6 +354,7 @@
 static PyObject *rolesForPermissionOn(PyObject *self, PyObject *args);
 static PyObject *module_guarded_getattr(PyObject *self, PyObject *args);
 static PyObject *module_aq_validate(PyObject *self, PyObject *args);
+static PyObject *module_setDefaultBehaviors(PyObject *self, PyObject *args);
 static PyObject *c_rolesForPermissionOn(PyObject *self, PyObject *perm,
                                         PyObject *object, PyObject *deflt);
 
@@ -395,7 +396,12 @@
 		(PyCFunction)module_aq_validate,
 		METH_VARARGS,
 		""
-        },               
+        },
+	{"setDefaultBehaviors",
+		(PyCFunction)module_setDefaultBehaviors,
+		METH_VARARGS,
+		""
+	},
 	{ NULL, NULL }
 };
 
@@ -449,7 +455,7 @@
 	NULL,					/* tp_next	*/
 #endif
 	METHOD_CHAIN(ZopeSecurityPolicy_methods),/* methods	*/
-	(void*)(EXTENSIONCLASS_BINDABLE_FLAG),		/* flags	*/
+	EXTENSIONCLASS_BINDABLE_FLAG,		/* flags	*/
 };
 
 
@@ -567,8 +573,11 @@
 	NULL,					/* tp_next	*/
 #endif
 	METHOD_CHAIN(PermissionRole_methods),	/* methods	*/
-	(void*)(EXTENSIONCLASS_BINDABLE_FLAG) /*|
+	EXTENSIONCLASS_BINDABLE_FLAG/*|
 	EXTENSIONCLASS_INSTDICT_FLAG*/,		/* flags	*/
+	NULL,					/* Class dict	*/
+	NULL,					/* bases	*/
+	NULL,					/* reserved	*/
 };
 
 static char imPermissionRole__doc__[] = "imPermissionRole C implementation";
@@ -629,7 +638,7 @@
 	NULL,					/* tp_next	*/
 #endif
 	METHOD_CHAIN(imPermissionRole_methods), /* methods	*/
-	(void*)(EXTENSIONCLASS_BINDABLE_FLAG),		/* flags	*/
+	EXTENSIONCLASS_BINDABLE_FLAG,		/* flags	*/
 };
 
 
@@ -639,6 +648,7 @@
 */
 
 static PyObject *Containers = NULL;
+static PyObject *ContainerAssertions = NULL;
 static PyObject *Unauthorized = NULL;
 static PyObject *LOG = NULL;
 static PyObject *PROBLEM = NULL;
@@ -657,9 +667,14 @@
 static PyObject *_proxy_roles_str = NULL;
 static PyObject *allowed_str = NULL;
 static PyObject *getOwner_str = NULL;
+static PyObject *getPhysicalRoot_str = NULL;
 static PyObject *checkPermission_str = NULL;
 static PyObject *getSecurityManager = NULL;
+static PyObject *unrestrictedTraverse_str = NULL;
 static PyObject *aq_validate = NULL;
+static PyObject *aq_parent_str = NULL;
+static PyObject *_check_context_str = NULL;
+
 static int ownerous = 1;
 static int authenticated = 1;
 
@@ -694,6 +709,15 @@
           return -1;
 	UNLESS (allowed_str = PyString_FromString("allowed")) return -1;
 	UNLESS (getOwner_str = PyString_FromString("getOwner")) return -1;
+	UNLESS (getPhysicalRoot_str = PyString_FromString("getPhysicalRoot")) 
+	  return -1;
+	UNLESS (aq_parent_str = PyString_FromString("aq_parent")) return -1;
+	UNLESS (_check_context_str = PyString_FromString("_check_context")) 
+	  return -1;
+	UNLESS (unrestrictedTraverse_str = PyString_FromString(
+					   "unrestrictedTraverse")) 
+	  return -1;
+
 	UNLESS (checkPermission_str = PyString_FromString("checkPermission")) 
           return -1;
         UNLESS (__allow_access_to_unprotected_subobjects__ = 
@@ -701,10 +725,6 @@
                 "__allow_access_to_unprotected_subobjects__"))
           return -1;
 
-	if (getenv("ZSP_OWNEROUS_SKIP") != NULL) ownerous = 0;
-	if (getenv("ZSP_AUTHENTICATED_SKIP") != NULL) authenticated = 0;
-
-
 	return 0;
 }
 
@@ -743,8 +763,18 @@
 	PyObject *rval = NULL;
 	PyObject *stack = NULL;
 	PyObject *user = NULL;
+
+
+	PyObject *method = NULL;
+	PyObject *tmp = NULL;
+	PyObject *udb = NULL;
+	PyObject *root = NULL;
+	PyObject *item = NULL;
+
 	char *sname;
 
+        int i, l, contains;
+        PyObject *r;
 
 	/*| def validate(self, accessed, container, name, value, context
 	**|	roles=_noroles ...
@@ -864,24 +894,38 @@
 		**|    tp = type(p)
 		**|    if tp is not IntType:
 		**|       if tp is DictType:
-		**|          p = p.get(name, None)
+                **|         if (isinstance(name, StringType) or
+                **|             isinstance(name, UnicodeType)):
+                **|             p=p.get(name, None)
+                **|         else:
+                **|             p = 1
 		**|       else:
 		**|          p = p(name, value)
 		*/
 
-		if (p) {
-			if (! PyInt_Check(p)) {
-				if (PyDict_Check(p)) {
-                                        ASSIGN(p, PyObject_GetItem(p, name));
-                                        if (p == NULL)
-                                          PyErr_Clear();
-				} else {
-                                  ASSIGN(p, callfunction2(p, name, value));
-                                  if (p == NULL)
-                                    goto err;
-				}
-			}
-		}
+		if (p) 
+                  {
+                    if (! PyInt_Check(p)) 
+                      {
+                        if (PyDict_Check(p)) 
+                          {
+                            if (PyString_Check(name) || PyUnicode_Check(name))
+                              {
+                                ASSIGN(p, PyObject_GetItem(p, name));
+                                if (p == NULL)
+                                  PyErr_Clear();
+                              }
+                            else
+                              p = PyInt_FromLong(1);
+                          } 
+                        else 
+                          {
+                            ASSIGN(p, callfunction2(p, name, value));
+                            if (p == NULL)
+                              goto err;
+                          }
+                      }
+                  }
 
 		/*| if not p:
 		**|     raise Unauthorized, cleanupName(name, value)
@@ -1016,23 +1060,154 @@
 	/*|    # Proxy roles, which are a lot safer now
 	**|    proxy_roles = getattr(eo, "_proxy_roles", None)
 	**|    if proxy_roles:
-	**|       for r in 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.getOwner()
+	**|        # Sigh; the default userfolder doesn't return users wrapped
+	**|        if owner and not hasattr(owner, 'aq_parent'):
+	**|            udb=eo.getOwner(1)[0]
+	**|            root=container.getPhysicalRoot()
+	**|            udb=root.unrestrictedTraverse(udb)
+	**|            owner=owner.__of__(udb)
+	**|                        
+	**|        if owner is not None:
+	**|            if not owner._check_context(container):
+	**|                # container is higher up than the owner, deny
+	**|                # access
+	**|                raise Unauthorized(name, value)
+	**|
+	**|        for r in proxy_roles:
 	**|          if r in roles: return 1
 	**|
-	**|       # proxy roles actually limit access!
-	**|	  raise Unauthorized, ('You are not authorized to access'
-	**|	      '<em>%s</em>.' % cleanupName(name, value))
+	**|        raise Unauthorized, ('You are not authorized to access'
+	**|	     '<em>%s</em>.' % cleanupName(name, value))
 	*/
 		proxy_roles = PyObject_GetAttr(eo, _proxy_roles_str);
-                Py_DECREF(eo);
+
 		if (proxy_roles == NULL) 
                   {
+		    Py_DECREF(eo);
                     PyErr_Clear();
                   }
                 else if (PyObject_IsTrue(proxy_roles)) 
                   {
-                    int i, l, contains=0;
-                    PyObject *r;
+
+		    /* patch!! --------------------------------  */
+
+		    method = PyObject_GetAttr(eo, getOwner_str);
+		    if (method == NULL) {
+		      Py_DECREF(eo);
+		      Py_DECREF(proxy_roles);
+		      goto err;
+		    }
+
+		    owner = PyObject_CallObject(method, NULL);
+		    Py_DECREF(method);
+		    if (owner == NULL) {
+		      Py_DECREF(eo);
+		      Py_DECREF(proxy_roles);
+		      goto err;
+		    }
+
+		    if (PyObject_IsTrue(owner)) {
+		      if (!PyObject_HasAttr(owner, aq_parent_str)) {
+			item = PyInt_FromLong(1);
+			if (item == NULL) {
+			  Py_DECREF(eo);
+			  Py_DECREF(proxy_roles);
+			  Py_DECREF(owner);
+			  goto err;
+			}
+
+		        tmp = callmethod1(eo, getOwner_str, item);
+			Py_DECREF(item);
+			if (tmp == NULL) {
+			  Py_DECREF(eo);
+			  Py_DECREF(proxy_roles);
+			  Py_DECREF(owner);
+			  goto err;
+			}
+
+			udb = PySequence_GetItem(tmp, 0);
+			Py_DECREF(tmp);
+			if (udb == NULL) {
+			  Py_DECREF(eo);
+		          Py_DECREF(proxy_roles);
+			  Py_DECREF(owner);
+			  goto err;
+			}
+
+			method = PyObject_GetAttr(container, 
+						  getPhysicalRoot_str);
+			if (method == NULL) {
+			  Py_DECREF(eo);
+		          Py_DECREF(proxy_roles);
+			  Py_DECREF(owner);
+			  Py_DECREF(udb);
+			  goto err;
+			}
+
+			root = PyObject_CallObject(method, NULL);
+			Py_DECREF(method);
+			if (root == NULL) {
+			  Py_DECREF(eo);
+		          Py_DECREF(proxy_roles);
+			  Py_DECREF(owner);
+			  Py_DECREF(udb);
+			  goto err;
+			}
+
+			ASSIGN(udb, callmethod1(root, unrestrictedTraverse_str,
+						udb)); 
+			Py_DECREF(root);
+			if (udb == NULL) {
+			  Py_DECREF(eo);
+		          Py_DECREF(proxy_roles);
+			  Py_DECREF(owner);
+			  goto err;
+			}
+
+			ASSIGN(owner, callmethod1(owner, __of__, udb));
+			Py_DECREF(udb);
+			if (owner == NULL) {
+			  Py_DECREF(eo);
+		          Py_DECREF(proxy_roles);
+			  goto err;
+			}
+
+		      }
+		    }
+
+		    Py_DECREF(eo);
+
+		    if (owner != Py_None) {
+		      tmp = callmethod1(owner,_check_context_str,
+					container
+					);
+		      if (tmp == NULL) {
+		        Py_DECREF(proxy_roles);
+			Py_DECREF(owner);
+			goto err;
+		      }
+
+		      if (!PyObject_IsTrue(tmp)) {
+	                Py_DECREF(proxy_roles);
+			Py_DECREF(owner);
+			Py_DECREF(tmp);
+			unauthErr(name, value);
+			goto err;
+		      }
+		      Py_DECREF(owner);
+		      Py_DECREF(tmp);
+		    }
+		    		    
+		    /* ------------------------------------------- */
+
+
+
+                    contains = 0;
                     if (PyTuple_Check(proxy_roles)) 
                       {
                         l=PyTuple_GET_SIZE(proxy_roles);
@@ -1063,9 +1238,9 @@
                     Py_DECREF(proxy_roles);
 
                     if (contains > 0)
-                      rval = PyInt_FromLong(1);
+                      rval = PyInt_FromLong(contains);
                     else if (contains == 0) {
-                      unauthErr(name, value);
+		      unauthErr(name, value);
                     }
                     goto err;
                   }
@@ -1939,16 +2114,74 @@
         }
 
       /*
-        if Containers(type(inst)):
-            # Simple type.  Short circuit.
-            return v
+            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
       */
-      t=callfunction1(Containers, OBJECT(inst->ob_type));
-      if (t==NULL) goto err;
-      i=PyObject_IsTrue(t);
-      if (i < 0) goto err;
-      Py_DECREF(t);
-      if (i) 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 (attrv->ob_type->tp_call)
+                        {
+                          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 (t->ob_type->tp_call)
+                {
+                  PyObject *ignored;
+                  ignored = callfunction2(t, name, v);
+                  if (ignored == NULL)
+                    {
+                      /* veto */
+                      Py_DECREF(v);
+                      return NULL;
+                    }
+                  Py_DECREF(ignored);
+                }
+              return v;
+            }
+        }
 
       /*
         # Filter out the objects we can't access.
@@ -1979,6 +2212,7 @@
       return NULL;
     }
 
+ unauth:
   /* raise Unauthorized, name */
   PyErr_SetObject(Unauthorized, name);
   return NULL;
@@ -2019,6 +2253,21 @@
 }
 
 static PyObject *
+module_setDefaultBehaviors(PyObject *ignored, PyObject *args)
+{
+  PyObject *result = NULL;
+  int own, auth;
+
+  if (PyArg_ParseTuple(args, "ii:setDefaultBehaviors", &own, &auth)) {
+    ownerous = own;
+    authenticated = authenticated;
+    result = Py_None;
+    Py_INCREF(result);
+  }
+  return result;
+}
+
+static PyObject *
 dtml_guarded_getattr(PyObject *self, PyObject *args)
 {
   PyObject *ob, *name, *default_=0, *validate;
@@ -2070,8 +2319,13 @@
 
 	if (ZopeSecurityPolicy_setup() < 0) return;
 
+	ZopeSecurityPolicyType.tp_getattro =
+		(getattrofunc) PyExtensionClassCAPI->getattro;
+
+	ExtensionClassGetattro= PyExtensionClassCAPI->getattro;
 
-	ExtensionClassGetattro= Py_FindAttr;
+	imPermissionRoleType.tp_getattro =
+		(getattrofunc) PyExtensionClassCAPI->getattro;
 
 	module = Py_InitModule3("cAccessControl",
 		cAccessControl_methods,
@@ -2110,6 +2364,7 @@
 
 	IMPORT(module, "AccessControl.SimpleObjectPolicies");
 	GETATTR(module, Containers);
+	GETATTR(module, ContainerAssertions);
 	Py_DECREF(module);
 	module = NULL;
 




More information about the Zope-Checkins mailing list