[Zope3-checkins] SVN: Zope3/trunk/src/ Implemented a restricted
Python interpreter for TALES expressions.
Fred L. Drake, Jr.
fred at zope.com
Thu Jul 22 16:44:21 EDT 2004
Log message for revision 26688:
Implemented a restricted Python interpreter for TALES expressions.
- Copied the RestrictedPython package from the Zope 2 trunk, rev 26679
(we're not using most of it, but copying this as a unit makes the
most sense)
- Created a new package, zope.restrictedpython, that uses
RestrictedPython to implement the corresponding Zope 3 structures
- Use zope.restrictedpython in zope.app.pagetemplate to provide
restricted execution for Python expressions in page templates
Changed:
A Zope3/trunk/src/RestrictedPython/
U Zope3/trunk/src/zope/app/pagetemplate/engine.py
A Zope3/trunk/src/zope/restrictedpython/
A Zope3/trunk/src/zope/restrictedpython/DEPENDENCIES.cfg
A Zope3/trunk/src/zope/restrictedpython/README.txt
A Zope3/trunk/src/zope/restrictedpython/__init__.py
A Zope3/trunk/src/zope/restrictedpython/mutator.py
A Zope3/trunk/src/zope/restrictedpython/rcompile.py
A Zope3/trunk/src/zope/restrictedpython/tests.py
-=-
Copied: Zope3/trunk/src/RestrictedPython (from rev 26679, Zope/trunk/lib/python/RestrictedPython)
Modified: Zope3/trunk/src/zope/app/pagetemplate/engine.py
===================================================================
--- Zope3/trunk/src/zope/app/pagetemplate/engine.py 2004-07-22 20:35:49 UTC (rev 26687)
+++ Zope3/trunk/src/zope/app/pagetemplate/engine.py 2004-07-22 20:44:21 UTC (rev 26688)
@@ -29,6 +29,7 @@
from zope.component.exceptions import ComponentLookupError
from zope.exceptions import NotFoundError
from zope.proxy import removeAllProxies
+from zope.restrictedpython import rcompile
from zope.security.proxy import ProxyFactory
from zope.security.builtins import RestrictedBuiltins
from zope.i18n import translate
@@ -54,6 +55,23 @@
def __init__(self, name, expr, engine):
super(ZopePathExpr, self).__init__(name, expr, engine, zopeTraverser)
+
+# Create a version of the restricted built-ins that uses a safe
+# version of getattr() that wraps values in security proxies where
+# appropriate:
+
+_marker = object()
+
+def safe_getattr(object, name, default=_marker):
+ if default is _marker:
+ return ProxyFactory(getattr(object, name))
+ else:
+ return ProxyFactory(getattr(object, name, default))
+
+RestrictedBuiltins = RestrictedBuiltins.copy()
+RestrictedBuiltins["getattr"] = safe_getattr
+
+
class ZopePythonExpr(PythonExpr):
def __call__(self, econtext):
@@ -61,6 +79,10 @@
vars = self._bind_used_names(econtext, RestrictedBuiltins)
return eval(self._code, vars)
+ def _compile(self, text, filename):
+ return rcompile.compile(text, filename, 'eval')
+
+
class ZopeContextBase(Context):
"""Base class for both trusted and untrusted evaluation contexts."""
@@ -205,6 +227,16 @@
...
ForbiddenAttribute: ('_getframe', <module 'sys' (built-in)>)
+ The results of Python expressions evaluated by this engine are
+ wrapped in security proxies::
+
+ >>> r = context.evaluate('python: {12: object()}.values')
+ >>> type(r)
+ <type 'zope.security._proxy._Proxy'>
+ >>> r = context.evaluate('python: {12: object()}.values()[0].__class__')
+ >>> type(r)
+ <type 'zope.security._proxy._Proxy'>
+
"""
_create_context = ZopeContext
Added: Zope3/trunk/src/zope/restrictedpython/DEPENDENCIES.cfg
===================================================================
--- Zope3/trunk/src/zope/restrictedpython/DEPENDENCIES.cfg 2004-07-22 20:35:49 UTC (rev 26687)
+++ Zope3/trunk/src/zope/restrictedpython/DEPENDENCIES.cfg 2004-07-22 20:44:21 UTC (rev 26688)
@@ -0,0 +1,2 @@
+zope.testing
+RestrictedPython
Added: Zope3/trunk/src/zope/restrictedpython/README.txt
===================================================================
--- Zope3/trunk/src/zope/restrictedpython/README.txt 2004-07-22 20:35:49 UTC (rev 26687)
+++ Zope3/trunk/src/zope/restrictedpython/README.txt 2004-07-22 20:44:21 UTC (rev 26688)
@@ -0,0 +1,69 @@
+==================================
+Support for Restricted Python Code
+==================================
+
+This package, `zope.restrictedpython`, provides a way to compile
+untrusted Python code so that it can be executed safely.
+
+This currently only supports expressions (compile()'s "eval" mode);
+support for "exec" and "single" modes will be added later.
+
+This form of restricted Python assumes that security proxies will be
+used to protect assets. Given this, the only thing that actually
+needs to be done differently by the generated code is to ensure that
+all attribute lookups go through a safe version of the getattr()
+function that's been provided in the built-in functions used in the
+execution environment. No other special treatment is needed to
+support safe expression evaluation. (Additional behaviors are needed
+for the "exec" and "single" modes.)
+
+The implementation makes use of the `RestrictedPython` package,
+originally written for Zope 2. There is a new AST re-writer in
+`zope.restrictedpython.mutator` which performs the
+tree-transformation, and a top-level `compile()` function in
+`zope.restrictedpython.rcompile`; the later is what client
+applications are expected to use.
+
+The signature of the `compile()` function is very similar to that of
+Python's built-in `compile()` function::
+
+ compile(source, filename, mode)
+
+Using it is equally simple::
+
+ >>> from zope.restrictedpython.rcompile import compile
+
+ >>> code = compile("21 * 2", "<string>", "eval")
+ >>> eval(code)
+ 42
+
+What's interesting about the restricted code is that all attribute
+lookups go through the `getattr()` function. This is generally
+provided as a built-in function in the restricted environment::
+
+ >>> def mygetattr(object, name, default="Yahoo!"):
+ ... marker = []
+ ... print "Looking up", name
+ ... if getattr(object, name, marker) is marker:
+ ... return default
+ ... else:
+ ... return "Yeehaw!"
+
+ >>> import __builtin__
+ >>> builtins = __builtin__.__dict__.copy()
+ >>> builtins["getattr"] = mygetattr
+
+ >>> def reval(source):
+ ... code = compile(source, "README.txt", "eval")
+ ... globals = {"__builtins__": builtins}
+ ... return eval(code, globals, {})
+
+ >>> reval("(42).__class__")
+ Looking up __class__
+ 'Yeehaw!'
+ >>> reval("(42).not_really_there")
+ Looking up not_really_there
+ 'Yahoo!'
+
+This allows a `getattr()` to be used that ensures the result of
+evaluation is a security proxy.
Property changes on: Zope3/trunk/src/zope/restrictedpython/README.txt
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:eol-style
+ native
Added: Zope3/trunk/src/zope/restrictedpython/__init__.py
===================================================================
--- Zope3/trunk/src/zope/restrictedpython/__init__.py 2004-07-22 20:35:49 UTC (rev 26687)
+++ Zope3/trunk/src/zope/restrictedpython/__init__.py 2004-07-22 20:44:21 UTC (rev 26688)
@@ -0,0 +1 @@
+# This directory is a Python package.
Property changes on: Zope3/trunk/src/zope/restrictedpython/__init__.py
___________________________________________________________________
Name: svn:mime-type
+ text/x-python
Name: svn:eol-style
+ native
Added: Zope3/trunk/src/zope/restrictedpython/mutator.py
===================================================================
--- Zope3/trunk/src/zope/restrictedpython/mutator.py 2004-07-22 20:35:49 UTC (rev 26687)
+++ Zope3/trunk/src/zope/restrictedpython/mutator.py 2004-07-22 20:44:21 UTC (rev 26688)
@@ -0,0 +1,57 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Modify AST to include security checks.
+
+RestrictionMutator modifies a tree produced by
+compiler.transformer.Transformer, restricting and enhancing the
+code in various ways before sending it to pycodegen.
+
+$Revision: 1.13 $
+"""
+
+from RestrictedPython.SelectCompiler import ast, OP_ASSIGN, OP_DELETE, OP_APPLY
+
+
+# The security checks are performed by a set of six functions that
+# must be provided by the restricted environment.
+
+_getattr_name = ast.Name("getattr")
+
+
+class RestrictionMutator:
+
+ def __init__(self):
+ self.errors = []
+ self.warnings = []
+ self.used_names = {}
+
+ def error(self, node, info):
+ """Records a security error discovered during compilation."""
+ lineno = getattr(node, 'lineno', None)
+ if lineno is not None and lineno > 0:
+ self.errors.append('Line %d: %s' % (lineno, info))
+ else:
+ self.errors.append(info)
+
+ def visitGetattr(self, node, walker):
+ """Converts attribute access to a function call.
+
+ 'foo.bar' becomes 'getattr(foo, "bar")'.
+
+ Also prevents augmented assignment of attributes, which would
+ be difficult to support correctly.
+ """
+ node = walker.defaultVisitNode(node)
+ return ast.CallFunc(_getattr_name,
+ [node.expr, ast.Const(node.attrname)])
Property changes on: Zope3/trunk/src/zope/restrictedpython/mutator.py
___________________________________________________________________
Name: svn:mime-type
+ text/x-python
Name: svn:eol-style
+ native
Added: Zope3/trunk/src/zope/restrictedpython/rcompile.py
===================================================================
--- Zope3/trunk/src/zope/restrictedpython/rcompile.py 2004-07-22 20:35:49 UTC (rev 26687)
+++ Zope3/trunk/src/zope/restrictedpython/rcompile.py 2004-07-22 20:44:21 UTC (rev 26688)
@@ -0,0 +1,44 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""compile() equivalent that produces restricted code.
+
+Only 'eval' is supported at this time.
+
+$Id$
+"""
+
+import compiler.pycodegen
+
+import RestrictedPython.RCompile
+
+import zope.restrictedpython.mutator
+
+
+def compile(text, filename, mode):
+ if mode != "eval":
+ raise ValueError("only 'eval' mode is supported")
+ gen = RExpression(text, filename)
+ gen.compile()
+ return gen.getCode()
+
+
+class RExpression(RestrictedPython.RCompile.RestrictedCompileMode):
+
+ mode = "eval"
+ CodeGeneratorClass = compiler.pycodegen.ExpressionCodeGenerator
+
+ def __init__(self, source, filename):
+ RestrictedPython.RCompile.RestrictedCompileMode.__init__(
+ self, source, filename)
+ self.rm = zope.restrictedpython.mutator.RestrictionMutator()
Property changes on: Zope3/trunk/src/zope/restrictedpython/rcompile.py
___________________________________________________________________
Name: svn:mime-type
+ text/x-python
Name: svn:eol-style
+ native
Added: Zope3/trunk/src/zope/restrictedpython/tests.py
===================================================================
--- Zope3/trunk/src/zope/restrictedpython/tests.py 2004-07-22 20:35:49 UTC (rev 26687)
+++ Zope3/trunk/src/zope/restrictedpython/tests.py 2004-07-22 20:44:21 UTC (rev 26688)
@@ -0,0 +1,23 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Tests for zope.restrictedpython.
+
+$Id$
+"""
+import os
+import zope.testing.doctestunit
+
+
+def test_suite():
+ return zope.testing.doctestunit.DocFileSuite("README.txt")
Property changes on: Zope3/trunk/src/zope/restrictedpython/tests.py
___________________________________________________________________
Name: svn:mime-type
+ text/x-python
Name: svn:eol-style
+ native
More information about the Zope3-Checkins
mailing list