[Zope-dev] PageTemplateFile vs. Bindings vs. Security

Jamie Heilman jamie at audible.transient.net
Mon Mar 22 19:42:32 EST 2004


So... remember way back when Brian warned about the binding breakage
due to the improved security checks?  It just bit me in a way I didn't
forsee.  I forgot that PageTemplates use bindings too, which means
those changes affect more than just PythonScripts they affect Products
that use PageTemplateFile methods.  My product had declared its object
instances to be private, and in doing so it totally breaks the ability
to use PageTemplateFile methods.  This sucks.

Using DTML for product methods goes against the fiber of my being, I
just can't bring myself to do it; the namespace pollution as
programing paradigm is so frustrating it just makes me want to throw
things.  But DTMLFile has a huge advantage ... it does the Right Thing
with respect to Zope security.  It ignores it completely.

Paradoxically, by ignoring Zope's security framework in the context of
on-disk methods this actually improves Zope's overall security.  It
allows you to fully take advantage of the API seperation available to
Products.  To briefly enumerate, you've got 3 basic types of methods:

def _python_only_methods():
    """docstring doesn't "matter" as this can't be published or
       accessed TTW, security declarations are superfluous, can't be
       accessed by RestrictedPython either"""

def python_or_RestrictedPython_methods():
    # no docstring ensures its not publishable, security declarations
    # are necessary to dictate RestrictedPython's privileges
    pass

def publishable_python_or_RestrictedPython_methods():
    """docstring dictates publishablility, security declarations are
       necessary and dictate both RestrictedPython's privileges and TTW
       privileges"""

Now DTMLFile does its work with the privileges of "python" code, which
is great because it means you can define methods which generate
content fragments without any restrictions on what APIs it can and
can't use.  This is useful--more on why in a sec.

Conversely the PageTemplateFile does it work with the privileges of
"RestrictedPython" code, which might seem great at first, ("More
security? What can possibly be bad about that?!") but rapidly wears
thin when you try to use PageTemplateFiles in API code, and screws
Product authors who were trying to write secure code.

To illustrate the first point where PageTemplateFile forces a weakened
API, consider the case of Tabs.manage_tabs() ... this method must be
declared *public* so that Products using PageTemplateFile can access
it.  The caller's security context is taken into account with
PageTemplateFiles and as 2 different products using PageTemplateFile
methods might require completely different permissions to access the
method which in turn relies upon Tabs.manage_tabs() the only way to
satisfy all possible permission combinations is to just give up and
declare the method public so it always succeeds.  Products using
DTMLFile OTOH don't care, it could be totally private, as it *should*
be, and DTMLFile methods would still be able to call it and use the
results to display content without regards to callers security
context, this makes DTMLFiles useful because you can maintain the
integrity of your API and not expose stuff to RestrictedPython that
true RestrictedPython has no business calling.  If only DTML wasn't
such a horrible, syntactically braindamaged, stack-bound HELL to work
with!

But DTML is hell, and thats not going to change, its better to focus
energies on the future which is ZPT, and I assert that
PageTemplateFile behavior needs to change.

Back to the second point, that the current behavior screws Product
authors trying to write secure code.  My product called
security.declareObjectPrivate() because this is the only way I know of
to ensure a product and its attributes are safe from tampering,
and until the Binding changes, I thought this was a great deal.  Now
that the hole in bindings have been fixed though it turns out that
because my product uses PageTemplateFile methods which in turn pay
attention to bindings, and, unfortunately, pay attention to the
callers security context as well, none of those methods work anymore,
they raise Unauthorized: Not authorized to access binding: container

I can fix this by changing my object security declaration to be public
or restricted to a permission, but that has side effects that I don't
want, namely opening my object instances up to tampering from within
RestrictedPython given the appropriate security context.  Given that
my need to have the object instance completely private and my desire
to avoid DTML are now in direct conflict I'm basically forced to
choose between a range of compromises and I don't like any of them.

So here's the questions I have for you all... is there a way to
declare appropriate security on the bindings that are screwing me
right now from within my product code so that I can selectively poke
holes to allow container access where needed, or am I to be forcibly
coerced into exposing my object to restricted code?  And two, assuming
I haven't overlooked some detail about why forcing PageTemplateFile to
work within the calling security context is a good thing...  Shouldn't
we fix PageTemplateFile to work like DTMLFile wrt security?  How hard
is it going to be to do that?

-- 
Jamie Heilman                     http://audible.transient.net/~jamie/
"...thats the metaphorical equivalent of flopping your wedding tackle
 into a lion's mouth and flicking his lovespuds with a wet towel, pure
 insanity..."                                           -Rimmer



More information about the Zope-Dev mailing list