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 <[EMAIL PROTECTED]> 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 > _______________________________________________ Zope maillist - Zope@zope.org http://mail.zope.org/mailman/listinfo/zope ** No cross posts or HTML encoding! ** (Related lists - http://mail.zope.org/mailman/listinfo/zope-announce http://mail.zope.org/mailman/listinfo/zope-dev )