[Zope] External Methods, Proxy Roles, and Executable Security

George Lee georgeleejr at gmail.com
Sun Nov 20 12:47:51 EST 2005


Great, thanks much.

Is there much buzz about this in CMF developer land? It seems like
proper proxy roles handling, and like you said what Zope 3 security
will do to it, are pretty important and will come up quite often (all
I was doing, after all, was trying to move an object upon workflow
change!).

Peace,
George


On 11/19/05, Dieter Maurer <dieter at handshake.de> wrote:
> George Lee wrote at 2005-11-19 00:46 -0500:
> >In CMFCore 1.5.4:
> >
> >If a low-security-clearance user calls an external method that pastes
> >an object from a PortalFolder, he gets an error because the following
> >line in CMFCore.PortalFolder fails:
> >
> >if not sm.checkPermission(DeleteObjects, parent):
> >   raise AccessControl_Unauthorized
> >
> >This is even the case if "sm.checkPermission" is changed to
> >"_checkPermission", which takes into account proxy roles. The external
> >method does not allow proxy roles attached, so I can't just add a
> >"Manager" proxy role.
> >
> >Because I called the pasting in an external method, I expected it to
> >go through without security problems! Is this a right expectation /
> >and a bug, or a wrong expectation?
>
> It is the fate induced by explicit security checks.
> It will get much worse when the Zope 3 security comes into
> Zope 2 land: then even trusted code will have to deal with
> security proxied objects.
>
>
> We currently work around the problem that trusted code
> cannot have proxy roles with the following class:
>
> class ProxyContext:
>   def __init__(self, proxy_roles):
>     self._proxy_roles = tuple(proxy_roles)
>
>   def getOwner(self): return None
>   getWrappedOwner = getOwner
>
> This class emulates an object with proxy roles and can be pushed
> onto the "SecurityManager"s "context" stack like so:
>
>     sm = getSecurityManager()
>     context = ProxyContext(proxy_roles)
>     sm.addContext(context)
>     try:
>         # do something with "proxy_roles"
>         ...
>     finally: sm.removeContext(context)
>
>
> Note, that I had to fix (in a local copy) CMF's "_checkPermission"
> for this to work:
>
>    It had decided to emulate Zope's proxy role checking only
>    approximately -- incorrectly for a "None" owner.
>
> My fix looks like this:
>
> security.declarePrivate('_checkPermission')
> def _checkPermission(permission, obj):
>     """ Check if the current user has the permission on the given object.
>     """
>     # this code is ported from ZopeSecurityPolicy.checkPermission
>     roles = rolesForPermissionOn(permission, obj)
>     if isinstance(roles, basestring):
>         roles = [roles]
>     context = getSecurityManager()._context
>
>     # check executable owner and proxy roles
>     # this code is ported from ZopeSecurityPolicy.validate
>     stack = context.stack
>     if stack:
>         eo = stack[-1]
>         owner = eo.getOwner()
>         if owner is not None:
>             if not owner.allowed(obj, roles):
>                 return 0
>             # DM 2005-09-07: no reason to do it differently from Zope
>             #   It accepts "proxy_roles" even for a None owner
> ##            proxy_roles = getattr(eo, '_proxy_roles', None)
> ##            if proxy_roles:
> ##                if obj is not aq_base(obj):
> ##                    if not owner._check_context(obj):
> ##                        return 0
> ##                for r in proxy_roles:
> ##                    if r in roles:
> ##                         return 1
> ##                return 0
>         proxy_roles = getattr(eo, '_proxy_roles', None)
>         if proxy_roles:
>             if obj is not aq_base(obj):
>                 # DM 2005-09-07: do it as Zope does
>                 #if not owner._check_context(obj):
>                 if owner is not None and not owner._check_context(obj):
>                     return 0
>             for r in proxy_roles:
>                 if r in roles:
>                      return 1
>             return 0
>
>     return context.user.allowed(obj, roles)
>
>
> If you are interested in using this approach, you
> should probably file another CMF bug report about the
> wrong handling of proxy roles in "_checkPermission".
> I explicitely allow you to attach the fix given above.
>
>
> --
> Dieter
>


More information about the Zope mailing list