[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
Hi Terry, just a short hint: [...]
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.
[...] Starting Zope with the envoronment variable: ZOPE_SECURITY_POLICY=PYTHON should give a better traceback -- currently some code is hidden from the traceback, as it is implemented as a C extension. Maybe Shane's VerboseSecurity does tell you more? I found it quite useful (the above hint is actually from the readme of that product). http://hathaway.freezope.org/Software/VerboseSecurity Cheers, Clemens
Thanks for the responses, but so far I'm still not there... :-( Oh, and BTW, I am *not* writing a replacement acl_user UserFolder, the name is an unfortunate name collision -- I probably need to change to "UserHomeFolder" or something, as it is more analogous to a user's home directory than to an authentication record. Sorry for any confusion that might've caused. On Tuesday 06 May 2003 10:48 am, Clemens Robbenhaar wrote:
Starting Zope with the envoronment variable:
ZOPE_SECURITY_POLICY=PYTHON
should give a better traceback -- currently some code is hidden from the traceback, as it is implemented as a C extension.
Maybe Shane's VerboseSecurity does tell you more? I found it quite useful (the above hint is actually from the readme of that product). http://hathaway.freezope.org/Software/VerboseSecurity
Oddly, it doesn't make any difference in the traceback. I still get the same error message. I'm pretty sure the environment variable worked, because it didn't on the 1st try and I got a log message from VerboseSecurity about it, then corrected it, and now I don't get the log message. Presumeably this means VerboseSecurity was happy with the monkey-patching results. But no more information appears -- when accessing this object *using restrictedTraverse()* I get the same message: """ Error Type: Unauthorized Error Value: You are not allowed to access terry in this context """ which occurs at: File /usr/local/narya/z2.5.1/lib/python/OFS/Traversable.py, line 130, in unrestrictedTraverse where I find: """ if restricted: container = N if has(o, 'im_self'): container = o.im_self elif (has(get(object, 'aq_base', object), name) and get(object, name) == o): container = object if (not securityManager.validate(object, container, name, o)): raise Unauthorized, name """ I also found a nice example of how python *can* be obfuscated if you try hard enough: """ get=getattr has=hasattr """ (Whoever you are, shame on you! ;-D) HOWEVER, after some fiddling, I got my object to publish when called by URL: http://my_site/Home/terry To achieve this, I changed my "UserPB" class to inherit from just "Acquisition.Explicit" and "Traversable", and I had to define "getId" and "index_html" methods, which I didn't have defined before. Now, obviously, it's not too logical (at least from a security perspective) for my object to be acquirable through URL, but not by restrictedTraverse(). What could do that? The only difference I know about is the "fake REQUEST" that restrictedTraverse() passes to __bobo_traverse__, which I discovered the last time I used it. I did trace the validate method down to being a method of "_policy" defined in the extension module "cAccessControl.c", although the code in that module is pretty much opaque to me (yes I know C, but it's been awhile, and it's obviously fairly complex in there). My next step is to hack Traversable.py and raise an exception that tells me what arguments validate() gets -- maybe that'll help. Thanks for any ideas. Part of my fascination with this problem is that I feel I will learn something about Zope's object publishing here. Terry -- Terry Hancock ( hancock at anansispaceworks.com ) Anansi Spaceworks http://www.anansispaceworks.com
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?]
Nope, there is no zope-products@zope.org or such. Currently product development is sort of a no-man's land, though leaning to zope@zope.org, which is part of the reason that list is so busy. --jcc
participants (3)
-
Clemens Robbenhaar -
J Cameron Cooper -
Terry Hancock