[Zope-Checkins] CVS: Zope3/lib/python/Zope/Security - RestrictedBuiltins.py:1.1.2.1 Checker.py:1.1.4.5 RestrictedInterpreter.py:1.1.4.2
Jim Fulton
jim@zope.com
Thu, 23 May 2002 14:01:52 -0400
Update of /cvs-repository/Zope3/lib/python/Zope/Security
In directory cvs.zope.org:/tmp/cvs-serv26429/lib/python/Zope/Security
Modified Files:
Tag: Zope-3x-branch
Checker.py RestrictedInterpreter.py
Added Files:
Tag: Zope-3x-branch
RestrictedBuiltins.py
Log Message:
This all started with wanting to be able to use url;view in a ZPT path. :)
That lead me to:
- Massive traversal refactoring.
Namespace handling is now centralized in Zope.App.Traversing.
- ZPT refactoring, including some renaming that touches pretty much everything. :)
- The application specific ZPT support was moved into
Zope.App.PageTemplate.
- To get page template files (for use in views):
from Zope.App.PageTemplate import ViewPageTemplateFile
- Fixed up security so that ZPT expressions only have access to
safe builtins and so that modules namespace does imports safely.
- Got ZPTPage working!
- renaming url to absolute_url and got absolute_url to work in paths.
- Cleaned up the (as yet unused) RestrictedInterpreter module in
Zope.Security. In particular, changed to use a separate
RestrictedBuiltins module.
=== Added File Zope3/lib/python/Zope/Security/RestrictedBuiltins.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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
#
##############################################################################
"""
Revision information:
$Id: RestrictedBuiltins.py,v 1.1.2.1 2002/05/23 18:01:22 jim Exp $
"""
import sys
def RestrictedBuiltins():
from Proxy import ProxyFactory
from Checker import NamesChecker
# It's better to say what is safe than it say what is not safe
_safe = [
'ArithmeticError', 'AssertionError', 'AttributeError',
'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError',
'Exception', 'FloatingPointError', 'IOError', 'ImportError',
'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt',
'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented',
'NotImplementedError', 'OSError', 'OverflowError', 'OverflowWarning',
'ReferenceError', 'RuntimeError', 'RuntimeWarning', 'StandardError',
'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError',
'SystemExit', 'TabError', 'TypeError', 'UnboundLocalError',
'UnicodeError', 'UserWarning', 'ValueError', 'Warning',
'ZeroDivisionError',
'__debug__', '__doc__', '__name__', 'abs', 'apply', 'buffer',
'callable', 'chr', 'classmethod', 'cmp', 'coerce', 'compile',
'complex', 'copyright', 'credits', 'delattr', 'dict',
'divmod', 'eval', 'filter', 'float', 'getattr', 'globals',
'hasattr', 'hash', 'hex', 'id', 'int', 'isinstance',
'issubclass', 'iter', 'len', 'license', 'list', 'locals',
'long', 'map', 'max', 'min', 'object', 'oct', 'ord', 'pow',
'property', 'quit', 'range', 'reduce', 'repr', 'round',
'setattr', 'slice', 'staticmethod', 'str', 'super', 'tuple',
'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip',
]
# XXX dir segfaults with a seg fault due to a bas tuple check in
# merge_class_dict in object.c. The assert macro seems to be doing
# the wrong think. Basically, if an object has bases, then bases
# is assumed to be a tuple.
# Anything that accesses an external file is a no no:
# 'open', 'execfile', 'file'
# We dont want restricted code to call exit: 'SystemExit', 'exit'
# Other no nos:
# help prints
# input does I/O
# raw_input does I/O
# intern's effect is too global
# reload does import, XXX doesn't it use __import__?
_builtinTypeChecker = NamesChecker(
['__str__', '__repr__', '__name__', '__module__',
'__bases__', '__call__'])
import __builtin__
builtins = {}
for name in _safe:
value = getattr(__builtin__, name)
if isinstance(value, type):
value = ProxyFactory(value, _builtinTypeChecker)
else:
value = ProxyFactory(value)
builtins[name] = value
def __import__(name, globals=None, locals=None, fromlist=()):
# Waaa, we have to emulate __import__'s weird semantics.
try:
module = sys.modules[name]
if fromlist:
return module
l = name.find('.')
if l < 0:
return module
return sys.modules[name[:l]]
except KeyError:
raise ImportError(name)
builtins['__import__'] = ProxyFactory(__import__)
return builtins
RestrictedBuiltins = RestrictedBuiltins()
=== Zope3/lib/python/Zope/Security/Checker.py 1.1.4.4 => 1.1.4.5 ===
from Interface import Interface
from _Proxy import _Proxy as Proxy
-from types import InstanceType, ClassType, FunctionType, MethodType, ModuleType
from ISecurityProxyFactory import ISecurityProxyFactory
from Zope.Security.SecurityManagement import getSecurityManager
-import sys, os
+import sys, os, types
if os.environ.get('ZOPE_WATCH_CHECKERS'):
WATCH_CHECKERS = 1
@@ -273,7 +272,7 @@
float: NoProxy,
long: NoProxy,
complex: NoProxy,
- type(None): NoProxy,
+ types.NoneType: NoProxy,
str: NoProxy,
unicode: NoProxy,
type(not 1): NoProxy, # Boolean, if available :)
@@ -291,13 +290,15 @@
# YAGNI: () a rock
tuple: NamesChecker(['__getitem__', '__getslice__',
'__contains__', '__len__', '__iter__']),
- InstanceType: _instanceChecker,
+ types.InstanceType: _instanceChecker,
Proxy: NoProxy,
- ClassType: _classChecker,
- FunctionType: _callableChecker,
- MethodType: _callableChecker,
+ types.ClassType: _classChecker,
+ types.FunctionType: _callableChecker,
+ types.MethodType: _callableChecker,
+ types.BuiltinFunctionType: _callableChecker,
+ types.BuiltinMethodType: _callableChecker,
type: _typeChecker,
- ModuleType: _moduleChecker,
+ types.ModuleType: _moduleChecker,
type(iter([])): NamesChecker(['next']),
type(Interface): _interfaceChecker,
}
=== Zope3/lib/python/Zope/Security/RestrictedInterpreter.py 1.1.4.1 => 1.1.4.2 ===
+#
+# Copyright (c) 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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
+#
+##############################################################################
+"""
+
+Revision information:
+$Id$
+"""
+
import sys
-from Zope.Security.Proxy import ProxyFactory
+from Proxy import ProxyFactory
+from RestrictedBuiltins import RestrictedBuiltins
class RestrictedInterpreter:
- ok_builtin_modules = ('audioop', 'array', 'binascii',
- 'cmath', 'errno', 'imageop',
- 'marshal', 'math', 'md5', 'operator',
- 'parser', 'regex', 'pcre', 'rotor', 'select',
- 'sha', '_sre', 'strop', 'struct', 'time')
-
- ok_sys_names = ('ps1', 'ps2', 'copyright', 'version',
- 'platform', 'exit', 'maxint')
-
- nok_builtin_names = ('open', 'file', 'reload', '__import__')
-
- def __init__(self, checker):
- self.checker = checker
- self.builtins = {}
- self.globals = {'__builtins__' : self.builtins}
- self.create_builtins()
+ def __init__(self):
+ self.globals = {'__builtins__' : RestrictedBuiltins}
def ri_exec(self, code):
# what is the type of code?
exec code in self.globals
-
- def create_builtins(self):
- import __builtin__
- for k, v in __builtin__.__dict__.iteritems():
- if k not in self.nok_builtin_names:
- self.builtins[k] = ProxyFactory(v, self.checker)
- self.builtins['__import__'] = ProxyFactory(self.ri_import)
-
- def ri_import(self, name, globals, locals, fromlist):
- # XXX handle fromlist
- return sys.modules[name]