Commit 1ac84e88 authored by Tres Seaver's avatar Tres Seaver

Rip out the C version of 'checkPermisison' altogether

It was only about 11 microseconds faster than the Python version on my
machine, and doesn't get called automagically the way 'validate' does.
parent 8bd1a3c1
...@@ -26,6 +26,10 @@ Zope Changes ...@@ -26,6 +26,10 @@ Zope Changes
Bugs Fixed Bugs Fixed
- AccessControl.ZopeSecurityPolicy: harmonize 'checkPermission'
with 'validate', checking ownership and proxy roles if an
executable object is on the stack.
- AccessControl.SecurityInfo: Fixed problem with - AccessControl.SecurityInfo: Fixed problem with
setPermissionDefault when the permission wasn't used anywhere setPermissionDefault when the permission wasn't used anywhere
else in the class to protect methods. else in the class to protect methods.
......
...@@ -18,7 +18,8 @@ try: ...@@ -18,7 +18,8 @@ try:
from cAccessControl import rolesForPermissionOn, \ from cAccessControl import rolesForPermissionOn, \
PermissionRole, imPermissionRole, _what_not_even_god_should_do, \ PermissionRole, imPermissionRole, _what_not_even_god_should_do, \
RestrictedDTMLMixin, aq_validate, guarded_getattr, \ RestrictedDTMLMixin, aq_validate, guarded_getattr, \
ZopeSecurityPolicy, setDefaultBehaviors setDefaultBehaviors
from cAccessControl import ZopeSecurityPolicy as cZopeSecurityPolicy
from cAccessControl import SecurityManager as cSecurityManager from cAccessControl import SecurityManager as cSecurityManager
except ImportError: except ImportError:
import sys import sys
...@@ -26,12 +27,17 @@ except ImportError: ...@@ -26,12 +27,17 @@ except ImportError:
del sys.modules[__name__] del sys.modules[__name__]
from ImplPython import RestrictedDTML, SecurityManager from ImplPython import RestrictedDTML, SecurityManager, ZopeSecurityPolicy
class RestrictedDTML(RestrictedDTMLMixin, RestrictedDTML): class RestrictedDTML(RestrictedDTMLMixin, RestrictedDTML):
"""A mix-in for derivatives of DT_String.String that adds Zope security.""" """A mix-in for derivatives of DT_String.String that adds Zope security."""
class ZopeSecurityPolicy(cZopeSecurityPolicy, ZopeSecurityPolicy):
"""A security manager provides methods for checking access and managing
executable context and policies
"""
class SecurityManager(cSecurityManager, SecurityManager): class SecurityManager(cSecurityManager, SecurityManager):
"""A security manager provides methods for checking access and managing """A security manager provides methods for checking access and managing
executable context and policies executable context and policies
......
...@@ -337,8 +337,6 @@ typedef struct { ...@@ -337,8 +337,6 @@ typedef struct {
*/ */
static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args); static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args);
static PyObject *ZopeSecurityPolicy_checkPermission(PyObject *self,
PyObject *args);
static void ZopeSecurityPolicy_dealloc(ZopeSecurityPolicy *self); static void ZopeSecurityPolicy_dealloc(ZopeSecurityPolicy *self);
...@@ -418,11 +416,6 @@ static PyMethodDef ZopeSecurityPolicy_methods[] = { ...@@ -418,11 +416,6 @@ static PyMethodDef ZopeSecurityPolicy_methods[] = {
METH_VARARGS, METH_VARARGS,
"" ""
}, },
{"checkPermission",
(PyCFunction)ZopeSecurityPolicy_checkPermission,
METH_VARARGS,
""
},
{ NULL, NULL } { NULL, NULL }
}; };
...@@ -1286,215 +1279,6 @@ static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args) { ...@@ -1286,215 +1279,6 @@ static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args) {
} }
/*
** ZopeSecurityPolicy_checkPermission
**
*/
static PyObject *ZopeSecurityPolicy_checkPermission(PyObject *self,
PyObject *args) {
/* return value */
PyObject *result = NULL;
/* arguments, not increfe'd */
PyObject *permission = NULL;
PyObject *object = NULL;
PyObject *context = NULL;
/* locals, XDECREF at exit */
PyObject *roles = NULL;
PyObject *user = NULL;
PyObject *stack = NULL;
PyObject *eo = NULL;
PyObject *owner = NULL;
PyObject *proxy_roles = NULL;
PyObject *method = NULL;
PyObject *wrappedowner = NULL;
PyObject *objectbase = NULL;
PyObject *incontext = NULL;
int contains = 0;
int iRole;
int length;
/*| def checkPermission(self, permission, object, context)
*/
if (unpacktuple3(args, "checkPermission", 3,
&permission, &object, &context) < 0)
return NULL;
/*| roles = rolesForPermissionOn(permission, object)
*/
roles = c_rolesForPermissionOn(permission, object, NULL, NULL);
if (roles == NULL)
return NULL;
/*| if type(roles) in (StringType, UnicodeType):
**| roles = [roles]
*/
if ( PyString_Check(roles) || PyUnicode_Check(roles) ) {
PyObject *role_list;
role_list = PyList_New(1);
if (role_list == NULL) goto cP_done;
/* Note: ref to roles is passed to the list object. */
PyList_SET_ITEM(role_list, 0, roles);
roles = role_list;
}
/*| # Check executable security
**| stack = context.stack
**| if stack:
*/
stack = PyObject_GetAttr(context, stack_str);
if (stack == NULL) goto cP_done;
if (PyObject_IsTrue(stack)) {
/*| eo = stack[-1]
**| # If the executable had an owner, can it execute?
**| owner = eo.getOwner()
**| if (owner is not None) and not owner.allowed(object, roles)
**| # We don't want someone to acquire if they can't
**| # get an unacquired!
**| return 0
*/
eo = PySequence_GetItem(stack, -1);
if (eo == NULL) goto cP_done;
if (ownerous) {
owner = PyObject_GetAttr(eo, getOwner_str);
if (owner) ASSIGN(owner, PyObject_CallObject(owner, NULL));
if (owner == NULL) goto cP_done;
if (owner != Py_None) {
ASSIGN(owner, PyObject_GetAttr(owner, allowed_str));
if (owner) ASSIGN(owner, callfunction2(owner, object, roles));
if (owner == NULL) goto cP_done;
if (! PyObject_IsTrue(owner)) {
result = PyInt_FromLong(0);
goto cP_done;
}
}
}
/*| # 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 object is not aq_base(object):
**| if not owner._check_context(object):
**| # object is higher up than the owner,
**| # deny access
**| return 0
**|
**| for r in proxy_roles:
**| if r in roles:
**| return 1
**| return 0
*/
proxy_roles = PyObject_GetAttr(eo, _proxy_roles_str);
if (proxy_roles == NULL) {
PyErr_Clear();
goto cP_check_user;
}
if (PyObject_IsTrue(proxy_roles)) {
method = PyObject_GetAttr(eo, getWrappedOwner_str);
if (method == NULL) goto cP_done;
wrappedowner = PyObject_CallObject(method, NULL);
if (wrappedowner == NULL) goto cP_done;
if (wrappedowner != Py_None) {
objectbase = aq_base(object);
if (object != objectbase) {
incontext = callmethod1(wrappedowner,
_check_context_str, object);
if (incontext == NULL) goto cP_done;
if ( ! PyObject_IsTrue(incontext)) {
ASSIGN(result, PyInt_FromLong(0));
goto cP_done;
}
}
}
}
if (PyTuple_Check(proxy_roles)) {
PyObject *proxy_role;
length = PyTuple_GET_SIZE(proxy_roles);
for (iRole=0; iRole < length; iRole++) {
proxy_role = PyTuple_GET_ITEM(proxy_roles, iRole);
/* proxy_role is not increfed */
if ((contains = PySequence_Contains(roles, proxy_role)))
break;
}
} else {
PyObject *proxy_role;
length = PySequence_Size(proxy_roles);
if (length < 0) goto cP_done;
for (iRole=0; contains == 0 && iRole < length; iRole++) {
proxy_role = PySequence_GetItem(proxy_roles, iRole);
if (proxy_role == NULL) goto cP_done;
/* proxy_role is increfed */
contains = PySequence_Contains(roles, proxy_role);
Py_DECREF(proxy_role);
}
}
/* If we have proxy roles, and they don't match, then lose
* (don't even check user roles at that point)
*/
if (contains < 0) contains = 0;
ASSIGN(result, PyInt_FromLong(contains));
goto cP_done;
} /* End of stack check */
cP_check_user:
/*| return context.user.allowed(object, roles)
*/
user = PyObject_GetAttr(context, user_str);
if (user != NULL) {
ASSIGN(user, PyObject_GetAttr(user, allowed_str));
if (user != NULL) {
result = callfunction2(user, object, roles);
if (result == NULL) goto cP_done;
}
}
cP_done:
Py_XDECREF(roles);
Py_XDECREF(user);
Py_XDECREF(stack);
Py_XDECREF(eo);
Py_XDECREF(owner);
Py_XDECREF(proxy_roles);
Py_XDECREF(method);
Py_XDECREF(wrappedowner);
Py_XDECREF(objectbase);
Py_XDECREF(incontext);
return result;
}
/* /*
** ZopeSecurityPolicy_dealloc ** ZopeSecurityPolicy_dealloc
** **
......
...@@ -415,7 +415,7 @@ class Python_ZSPTests(ZopeSecurityPolicyTestBase, ...@@ -415,7 +415,7 @@ class Python_ZSPTests(ZopeSecurityPolicyTestBase,
return ZopeSecurityPolicy return ZopeSecurityPolicy
class C_ZSPTests(ZopeSecurityPolicyTestBase, class C_ZSPTests(ZopeSecurityPolicyTestBase,
# ISecurityPolicyConformance, #XXX C version, how? ISecurityPolicyConformance,
): ):
def _getTargetClass(self): def _getTargetClass(self):
from AccessControl.ImplC import ZopeSecurityPolicy from AccessControl.ImplC import ZopeSecurityPolicy
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment