[Zope-dev] restrictedTraverse() security problem
Terry Hancock
hancock@anansispaceworks.com
Tue, 6 May 2003 10:41:58 -0700
[Resending to Zope-dev, because on reflection I think it
belongs there -- is there such a thing as a Zope product/
component developer list, or is this it?]
Hi All,
I have a call like this in restricted code:
Home.restrictedTraverse(username).profile()
which should call a method "profile" on a "UserPB" object
(this method is public information, and should be visible
to anyone).
The catch is that UserPB is a wrapper on a database
record, which I'm adding by using a __bobo_traverse__
method:
class Home(Folder):
meta_type = 'Narya-Home'
__implements__ = HomeAPI
security = ClassSecurityInfo()
security.setDefaultAccess("allow")
# ...
def __bobo_traverse__(self, REQUEST=None, name=None):
"""Get a UserFolder if it exists, or a UserPB."""
try:
return getattr(self, name)
except:
return self.getUser(name)
def getUser(self, username):
"""Retrieve UserPB object from username."""
return UserPB(self.DB._getUser(username=username)[0]).__of__(self)
class UserPB(Acquisition.Explicit, Item):
"""Basic wrapper for user data from database."""
__implements__ = UserPBI
# ...
def __init__(self, sqlres):
"""
Create a UserPB object by wrapping the SQL search result.
"""
for k in sqlres.__record_schema__.keys():
setattr(self, k, getattr(sqlres, k))
Accessing this causes an error
"""
Error Type: Unauthorized
Error Value: You are not allowed to access foo in this context
"""
(where "foo" is the actual username).
There is such a user, and the wrapper works perfectly when called
from unrestricted code, so the problem is definitely the security.
Here's the tail end of the traceback:
"""
File /usr/local/narya/z2.5.1/lib/python/DocumentTemplate/DT_Util.py, line 159, in eval
(Object: Home.restrictedTraverse(username).post_score(nposts, nrecent, nmarkup, ndoc, nfaq, nlink, ngallery, nproj))
(Info: username)
File <string>, line 0, in ?
File /usr/local/narya/z2.5.1/lib/python/OFS/Traversable.py, line 163, in restrictedTraverse
(Object: Home)
File /usr/local/narya/z2.5.1/lib/python/OFS/Traversable.py, line 130, in unrestrictedTraverse
(Object: Home)
Unauthorized: (see above)
"""
Which indeed is the security check:
[OFS/Traversable.py]:
"""
if (not securityManager.validate(object, container, name, o)):
raise Unauthorized, name
"""
So it seems I need to do something to "call off the dogs" here. I've
already set my default policy in "Home" to "allow" -- what's missing?
Do I have to explicitly call a security method to do that, or is
there an attribute or something needed? Also, is it really the Home
or the UserPB object whose security is not right?
I have not yet been able to figure out where "validate()" is actually
defined -- it seems the securityManager object expects to inherit
or acquire it from somewhere.
I realize there's probably another way to do the large task here,
but there are a number of reasons why it's more convenient to do
this mimicry trick to make a database record look like a simple
child object of Home -- not least of which is that I want to handle
them in parallel with persistent Zope objects ("UserFolder") which
implement an identical "UserPBI" interface.
Any suggestions or ideas would be very much appreciated!
Thanks,
Terry
--
Terry Hancock ( hancock at anansispaceworks.com )
Anansi Spaceworks http://www.anansispaceworks.com