Commit 31d14b29 authored by Martin Aspeli's avatar Martin Aspeli

Fix regression in treatment of trusted code in view page templates.

parent 03905b42
...@@ -27,6 +27,12 @@ Features Added ...@@ -27,6 +27,12 @@ Features Added
Bugs Fixed Bugs Fixed
++++++++++ ++++++++++
- Fixed a regression in Products.PageTemplates that meant filesystem templates
using Products.Five.browser.pagetemplatefile would treat TALES path
expressions (but not python expressions) as protected code and so attempt
to apply security. See original issue here:
http://codespeak.net/pipermail/z3-five/2007q2/002185.html
- LP #491249: fix tabindex on ZRDB connection test form. - LP #491249: fix tabindex on ZRDB connection test form.
- LP #490514: preserve tainting when calling into DTML from ZPT. - LP #490514: preserve tainting when calling into DTML from ZPT.
......
...@@ -42,15 +42,15 @@ class ViewPageTemplateFileTests(unittest.TestCase): ...@@ -42,15 +42,15 @@ class ViewPageTemplateFileTests(unittest.TestCase):
from zope.tales.pythonexpr import PythonExpr from zope.tales.pythonexpr import PythonExpr
from zope.contentprovider.tales import TALESProviderExpression from zope.contentprovider.tales import TALESProviderExpression
from Products.PageTemplates.DeferExpr import LazyExpr from Products.PageTemplates.DeferExpr import LazyExpr
from Products.PageTemplates.Expressions import ZopePathExpr from Products.PageTemplates.Expressions import TrustedZopePathExpr
from Products.PageTemplates.Expressions import SecureModuleImporter from Products.PageTemplates.Expressions import SecureModuleImporter
vptf = self._makeOne('seagull.pt') vptf = self._makeOne('seagull.pt')
engine = vptf.pt_getEngine() engine = vptf.pt_getEngine()
self.assertEqual(engine.types['standard'], ZopePathExpr) self.assertEqual(engine.types['standard'], TrustedZopePathExpr)
self.assertEqual(engine.types['path'], ZopePathExpr) self.assertEqual(engine.types['path'], TrustedZopePathExpr)
self.assertEqual(engine.types['exists'], ZopePathExpr) self.assertEqual(engine.types['exists'], TrustedZopePathExpr)
self.assertEqual(engine.types['nocall'], ZopePathExpr) self.assertEqual(engine.types['nocall'], TrustedZopePathExpr)
self.assertEqual(engine.types['string'], StringExpr) self.assertEqual(engine.types['string'], StringExpr)
self.assertEqual(engine.types['python'], PythonExpr) self.assertEqual(engine.types['python'], PythonExpr)
self.assertEqual(engine.types['not'], NotExpr) self.assertEqual(engine.types['not'], NotExpr)
......
...@@ -79,6 +79,26 @@ def boboAwareZopeTraverse(object, path_items, econtext): ...@@ -79,6 +79,26 @@ def boboAwareZopeTraverse(object, path_items, econtext):
request=request) request=request)
return object return object
def trustedBoboAwareZopeTraverse(object, path_items, econtext):
"""Traverses a sequence of names, first trying attributes then items.
This uses Zope 3 path traversal where possible and interacts
correctly with objects providing OFS.interface.ITraversable when
necessary (bobo-awareness).
"""
request = getattr(econtext, 'request', None)
path_items = list(path_items)
path_items.reverse()
while path_items:
name = path_items.pop()
if OFS.interfaces.ITraversable.providedBy(object):
object = object.unrestrictedTraverse(name)
else:
object = traversePathElement(object, name, path_items,
request=request)
return object
def render(ob, ns): def render(ob, ns):
"""Calls the object, possibly a document template, or just returns """Calls the object, possibly a document template, or just returns
it if not callable. (From DT_Util.py) it if not callable. (From DT_Util.py)
...@@ -104,11 +124,13 @@ def render(ob, ns): ...@@ -104,11 +124,13 @@ def render(ob, ns):
class ZopePathExpr(PathExpr): class ZopePathExpr(PathExpr):
_TRAVERSER = staticmethod(boboAwareZopeTraverse)
def __init__(self, name, expr, engine): def __init__(self, name, expr, engine):
if not expr.strip(): if not expr.strip():
expr = 'nothing' expr = 'nothing'
super(ZopePathExpr, self).__init__(name, expr, engine, super(ZopePathExpr, self).__init__(name, expr, engine,
boboAwareZopeTraverse) self._TRAVERSER)
# override this to support different call metrics (see bottom of # override this to support different call metrics (see bottom of
# method) and Zope 2's traversal exceptions (ZopeUndefs instead of # method) and Zope 2's traversal exceptions (ZopeUndefs instead of
...@@ -146,6 +168,9 @@ class ZopePathExpr(PathExpr): ...@@ -146,6 +168,9 @@ class ZopePathExpr(PathExpr):
return 1 return 1
return 0 return 0
class TrustedZopePathExpr(ZopePathExpr):
_TRAVERSER = staticmethod(trustedBoboAwareZopeTraverse)
class SafeMapping(MultiMapping): class SafeMapping(MultiMapping):
"""Mapping with security declarations and limited method exposure. """Mapping with security declarations and limited method exposure.
...@@ -347,11 +372,11 @@ class PathIterator(ZopeIterator): ...@@ -347,11 +372,11 @@ class PathIterator(ZopeIterator):
return False return False
return ob1 == ob2 return ob1 == ob2
def createZopeEngine(): def createZopeEngine(zpe=ZopePathExpr):
e = ZopeEngine() e = ZopeEngine()
e.iteratorFactory = PathIterator e.iteratorFactory = PathIterator
for pt in ZopePathExpr._default_type_names: for pt in zpe._default_type_names:
e.registerType(pt, ZopePathExpr) e.registerType(pt, zpe)
e.registerType('string', StringExpr) e.registerType('string', StringExpr)
e.registerType('python', ZRPythonExpr.PythonExpr) e.registerType('python', ZRPythonExpr.PythonExpr)
e.registerType('not', NotExpr) e.registerType('not', NotExpr)
...@@ -364,7 +389,7 @@ def createZopeEngine(): ...@@ -364,7 +389,7 @@ def createZopeEngine():
def createTrustedZopeEngine(): def createTrustedZopeEngine():
# same as createZopeEngine, but use non-restricted Python # same as createZopeEngine, but use non-restricted Python
# expression evaluator # expression evaluator
e = createZopeEngine() e = createZopeEngine(TrustedZopePathExpr)
e.types['python'] = PythonExpr e.types['python'] = PythonExpr
return e return e
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment