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 )