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

2005-11-22 Thread Dieter Maurer
George Lee wrote at 2005-11-20 12:47 -0500:
Is there much buzz about this in CMF developer land?

Apart from regular problem reports (usually in the Plone mailing list),
there are few talks about proxy roles.

-- 
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 )


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

2005-11-22 Thread Dieter Maurer
Jens Vagelpohl wrote at 2005-11-20 19:01 +0100:
 ...
IMHO proxy roles should be used extremely sparingly, if at all. They  
are a last resort and I personally never use them. Matter of fact I  
believe having to use them means the application design could use  
some improvement...

If something needs to be done with elevated privileges it should be  
in filesystem product code or, if that is not feasible, in an  
external method. At least that's my philosophy ;)

You have lost the thread's start:

  George's problem has been that he could not move an object
  in an *EXTERNAL METHOD*, i.e. in trusted filesystem code.

  He would have the same problem in a filesystem product.

  The problem is that CopySupport performs a local security
  check (in _verifyObjectPaste) independent from its caller
  (it does not matter whether the rename/move/copy was
  called from trusted or untrusted code).

  With appropriate proxy roles, an untrusted Python Script can perform some
  rename/move/copy that trusted code is unable to perform.

I assume you can agree that this is a somewhat unsane situation...


-- 
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 )


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

2005-11-22 Thread Jens Vagelpohl


On 22 Nov 2005, at 20:08, Dieter Maurer wrote:

You have lost the thread's start:

  George's problem has been that he could not move an object
  in an *EXTERNAL METHOD*, i.e. in trusted filesystem code.

  He would have the same problem in a filesystem product.

  The problem is that CopySupport performs a local security
  check (in _verifyObjectPaste) independent from its caller
  (it does not matter whether the rename/move/copy was
  called from trusted or untrusted code).

  With appropriate proxy roles, an untrusted Python Script can  
perform some

  rename/move/copy that trusted code is unable to perform.

I assume you can agree that this is a somewhat unsane situation...


Yes, that's very odd...  thanks for reminding me of the thread's start!

jens

___
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 )


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

2005-11-20 Thread George Lee
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 SecurityManagers 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 )


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

2005-11-20 Thread Jens Vagelpohl


On 20 Nov 2005, at 18:47, George Lee wrote:


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!).


IMHO proxy roles should be used extremely sparingly, if at all. They  
are a last resort and I personally never use them. Matter of fact I  
believe having to use them means the application design could use  
some improvement...


If something needs to be done with elevated privileges it should be  
in filesystem product code or, if that is not feasible, in an  
external method. At least that's my philosophy ;)


jens

___
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 )


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

2005-11-19 Thread Dieter Maurer
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 SecurityManagers 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 )