[Zope-Perl] security

Gisle Aas gisle@ActiveState.com
24 Jan 2001 11:23:06 -0800


"Chris McDonough" <chrism@digicool.com> writes:

> When a Perl Method returns a reference to a hash (or list), a perl ref
> object is returned to DTML or Python.  This is really neat.
> 
> There's one problem I can see, however:  Zope's security machinery inside
> DTML and Python Scripts expects instances to define a "__roles__" attribute
> so they may be accessed in TTW code.  Usually, I would do something like
> (from PerlMethod __init__.py's __call__ method):
> 
>  r = apply(perl.safecall, (root, mask, args))
>  roles = self.aq_acquire('__roles__') # grabs __roles__ of PerlM's
> container.
>  setattr(r, '__roles__', roles)
>  return r
> 
> .. but I can't setattr on the perlref instance, so this doesn't work.

The issue should be the same if you return a plain Python dict object,
or am I missing something.

> Without jiggering of the security machinery or a way to set __roles__ on
> perlref instances, doing (for example) in DTML:
> 
> <dtml-in>
>   <dtml-with "perlmwhichreturnshashref()">
>      <dtml-in keys>
>         <dtml-var sequence-item>
>      </dtml-in>
>   </dtml-with>
> </dtml-in>
> 
> ... doesn't work (the Zope security policy raises unauthorized at the point
> in which you attempt to access keys).
> 
> I *think* this can be solved in a couple of ways (each radically different):
> 
> - Do type conversion on hashrefs and arrayrefs to Python native datatypes
> (dict, list) in a return to Python if the hash or array keys/values are all
> string or number types.  This is potentially very expensive, and a little
> DWIMish.

You should really be able to force this yourself with a Script(Perl)
thing that does:

    my %hash = ( a => 42 );
    return Python::dict(%hash);

But I don't really see how that helps, as you can't set the __roles__
attribute on dicts either.  Currently this does not work because the
Python:: namespace is not really set up for safe compartments, but
that should not be hard to fix.  Setting up all the Python constructor
functions is probably needed if you want to reliably determine what
type a PerlMethod returns (int vs. float vs. strings).

> - Allow perlref instances in Python to have a __dict__ and let us assign to
> it from unrestricted code (so we can give it a __roles__).

I don't think this is the right thing to do.  How are we supposed to
keep the dict around if we pass this object though perl?  When it is
passed to perl the 'perl ref' is unwrapped and the dict is gone.  When
the hash reference is then passed back to python a new dict is set up
for it?  Does not sound clean to me.

> - Jigger the security machinery to do more DWIM.

I don't know much about that.

Regards,
Gisle