Commit 63089a55 authored by Evan Simpson's avatar Evan Simpson

Fixed access to 'repeat' variable, and security of all namespace variables,

with SecureMultiMap wrapper.

There's nothing you can't fix with another layer of indirection, except
for too many layers of indirection.
parent f9d24c8b
...@@ -89,7 +89,7 @@ Page Template-specific implementation of TALES, with handlers ...@@ -89,7 +89,7 @@ Page Template-specific implementation of TALES, with handlers
for Python expressions, Python string literals, and paths. for Python expressions, Python string literals, and paths.
""" """
__version__='$Revision: 1.9 $'[11:-2] __version__='$Revision: 1.10 $'[11:-2]
import re, sys import re, sys
from TALES import Engine, CompilerError, _valid_name, NAME_RE, \ from TALES import Engine, CompilerError, _valid_name, NAME_RE, \
...@@ -217,15 +217,9 @@ class PathExpr: ...@@ -217,15 +217,9 @@ class PathExpr:
path[i:i+1] = list(val) path[i:i+1] = list(val)
try: try:
__traceback_info__ = base __traceback_info__ = base
if var.has_key(base): has, ob = var.has_get(base)
ob = var[base] if not has:
else:
ob = contexts[base] ob = contexts[base]
# Work around lack of security declaration
if path and (ob is contexts['repeat']):
step = path.pop(0)
__traceback_info__ = (base, step)
ob = ob[step]
return restrictedTraverse(ob, path) return restrictedTraverse(ob, path)
except (AttributeError, KeyError, TypeError, IndexError), e: except (AttributeError, KeyError, TypeError, IndexError), e:
raise Undefined, (self._s, sys.exc_info()), sys.exc_info()[2] raise Undefined, (self._s, sys.exc_info()), sys.exc_info()[2]
...@@ -317,8 +311,8 @@ if sys.modules.has_key('Zope'): ...@@ -317,8 +311,8 @@ if sys.modules.has_key('Zope'):
# Bind template variables # Bind template variables
var = econtext.contexts['var'] var = econtext.contexts['var']
for vname in self._f_varnames: for vname in self._f_varnames:
val = var.get(vname, _marker) has, val = var.has_get(vname)
if val is not _marker: if has:
f.func_globals[vname] = val f.func_globals[vname] = val
# Execute the function in a new security context. # Execute the function in a new security context.
...@@ -364,8 +358,8 @@ else: ...@@ -364,8 +358,8 @@ else:
# Bind template variables # Bind template variables
var = econtext.contexts['var'] var = econtext.contexts['var']
for vname in self._f_varnames: for vname in self._f_varnames:
val = var.get(vname, _marker) has, val = var.has_get(vname)
if val is not _marker: if has:
f.func_globals[vname] = val f.func_globals[vname] = val
# Execute the function in a new security context. # Execute the function in a new security context.
...@@ -443,7 +437,7 @@ def restrictedTraverse(self, path): ...@@ -443,7 +437,7 @@ def restrictedTraverse(self, path):
o=object[name] o=object[name]
except (AttributeError, TypeError): except (AttributeError, TypeError):
raise AttributeError, name raise AttributeError, name
if not securityManager.validate(object, object, None, o): if not securityManager.validate(object, object, name, o):
raise 'Unauthorized', name raise 'Unauthorized', name
object = o object = o
......
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
An implementation of a generic TALES engine An implementation of a generic TALES engine
""" """
__version__='$Revision: 1.8 $'[11:-2] __version__='$Revision: 1.9 $'[11:-2]
import re, sys, ZTUtils import re, sys, ZTUtils
from MultiMapping import MultiMapping from MultiMapping import MultiMapping
...@@ -121,6 +121,28 @@ class RegistrationError(Exception): ...@@ -121,6 +121,28 @@ class RegistrationError(Exception):
class CompilerError(Exception): class CompilerError(Exception):
'''TALES Compiler Error''' '''TALES Compiler Error'''
class SecureMultiMap:
'''MultiMapping wrapper with security declarations'''
__allow_access_to_unprotected_subobjects__ = 1
def __init__(self, *dicts):
self._mm = apply(MultiMapping, dicts)
def __getitem__(self, index):
return self._mm[index]
def __len__(self):
return len(self._mm)
def _push(self, arg):
self._mm.push(arg)
def _pop(self):
return self._mm.pop()
def has_key(self, key):
return self._mm.has_key(key)
def has_get(self, key):
v = self._mm.get(key, self)
if v is self:
return 0, None
else:
return 1, v
class Iterator(ZTUtils.Iterator): class Iterator(ZTUtils.Iterator):
def __init__(self, name, seq, context): def __init__(self, name, seq, context):
ZTUtils.Iterator.__init__(self, seq) ZTUtils.Iterator.__init__(self, seq)
...@@ -204,15 +226,15 @@ class Context: ...@@ -204,15 +226,15 @@ class Context:
# These contexts will need to be pushed. # These contexts will need to be pushed.
self._current_ctxts = {'local': 1, 'repeat': 1} self._current_ctxts = {'local': 1, 'repeat': 1}
contexts['local'] = lv = MultiMapping() contexts['local'] = lv = SecureMultiMap()
init_local = contexts.get('local', None) init_local = contexts.get('local', None)
if init_local: if init_local:
lv.push(init_local) lv._push(init_local)
contexts['repeat'] = rep = SecureMultiMap()
contexts['loop'] = rep # alias
contexts['global'] = gv = contexts.copy() contexts['global'] = gv = contexts.copy()
gv['standard'] = contexts gv['standard'] = contexts
contexts['var'] = MultiMapping(gv, lv) contexts['var'] = SecureMultiMap(gv, lv)
contexts['repeat'] = rep = MultiMapping()
contexts['loop'] = rep # alias
def beginScope(self): def beginScope(self):
oldctxts = self._current_ctxts oldctxts = self._current_ctxts
...@@ -221,13 +243,13 @@ class Context: ...@@ -221,13 +243,13 @@ class Context:
for ctxname in oldctxts.keys(): for ctxname in oldctxts.keys():
# Push fresh namespace on each local stack. # Push fresh namespace on each local stack.
ctxts[ctxname] = ctx = {} ctxts[ctxname] = ctx = {}
self.contexts[ctxname].push(ctx) self.contexts[ctxname]._push(ctx)
def endScope(self): def endScope(self):
self._current_ctxts = ctxts = self._ctxts_pushed.pop() self._current_ctxts = ctxts = self._ctxts_pushed.pop()
# Pop the ones that were pushed at the beginning of the scope. # Pop the ones that were pushed at the beginning of the scope.
for ctxname in ctxts.keys(): for ctxname in ctxts.keys():
ctx = self.contexts[ctxname].pop() ctx = self.contexts[ctxname]._pop()
# Make sure there's no circular garbage # Make sure there's no circular garbage
ctx.clear() ctx.clear()
......
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