Commit 1502dc3c authored by Hanno Schlichting's avatar Hanno Schlichting

LP #1047318: Tighten import restrictions for restricted code.

parent a3639de7
...@@ -5,9 +5,11 @@ This file contains change information for the current Zope release. ...@@ -5,9 +5,11 @@ This file contains change information for the current Zope release.
Change information for previous versions of Zope can be found at Change information for previous versions of Zope can be found at
http://docs.zope.org/zope2/releases/. http://docs.zope.org/zope2/releases/.
2.12.24 (unreleased) 2.12.24 (2012-09-09)
-------------------- --------------------
- LP #1047318: Tighten import restrictions for restricted code.
- Fix a bug in ZopeSecurityPolicy.py. Global variable `rolesForPermissionOn` - Fix a bug in ZopeSecurityPolicy.py. Global variable `rolesForPermissionOn`
could be overridden if `__role__` had custom rolesForPermissionOn. could be overridden if `__role__` had custom rolesForPermissionOn.
......
...@@ -16,7 +16,7 @@ import os ...@@ -16,7 +16,7 @@ import os
from setuptools import setup, find_packages, Extension from setuptools import setup, find_packages, Extension
setup(name='Zope2', setup(name='Zope2',
version='2.12.24dev', version='2.12.24',
url='http://www.zope.org', url='http://www.zope.org',
license='ZPL 2.1', license='ZPL 2.1',
description='Zope2 application server / web framework', description='Zope2 application server / web framework',
......
...@@ -211,7 +211,9 @@ _appliedModuleSecurity = {} ...@@ -211,7 +211,9 @@ _appliedModuleSecurity = {}
def secureModule(mname, *imp): def secureModule(mname, *imp):
modsec = _moduleSecurity.get(mname, None) modsec = _moduleSecurity.get(mname, None)
if modsec is None: if modsec is None:
return if mname in _appliedModuleSecurity:
return sys.modules[mname]
return # no MSI, no module
if imp: if imp:
__import__(mname, *imp) __import__(mname, *imp)
......
...@@ -310,7 +310,7 @@ class GuardedListType: ...@@ -310,7 +310,7 @@ class GuardedListType:
return list.sorted(iterable, cmp=None, key=None, reverse=False) return list.sorted(iterable, cmp=None, key=None, reverse=False)
safe_builtins['list'] = GuardedListType() safe_builtins['list'] = GuardedListType()
class GuardedDictType: class GuardedDictType:
def __call__(self, *args, **kwargs): def __call__(self, *args, **kwargs):
return dict(*args, **kwargs) return dict(*args, **kwargs)
...@@ -329,20 +329,16 @@ def guarded_sum(sequence, start=0): ...@@ -329,20 +329,16 @@ def guarded_sum(sequence, start=0):
safe_builtins['sum'] = guarded_sum safe_builtins['sum'] = guarded_sum
def load_module(module, mname, mnameparts, validate, globals, locals): def load_module(module, mname, mnameparts, validate, globals, locals):
modules = sys.modules
while mnameparts: while mnameparts:
nextname = mnameparts.pop(0) nextname = mnameparts.pop(0)
if mname is None: if mname is None:
mname = nextname mname = nextname
else: else:
mname = '%s.%s' % (mname, nextname) mname = '%s.%s' % (mname, nextname)
nextmodule = modules.get(mname, None) # import (if not already imported) and check for MSI
if nextmodule is None: nextmodule = secureModule(mname, globals, locals)
nextmodule = secureModule(mname, globals, locals) if nextmodule is None: # not allowed
if nextmodule is None: return
return
else:
secureModule(mname)
if module and not validate(module, module, nextname, nextmodule): if module and not validate(module, module, nextname, nextmodule):
return return
module = nextmodule module = nextmodule
...@@ -440,7 +436,7 @@ def __imul__(x, y): ...@@ -440,7 +436,7 @@ def __imul__(x, y):
def __idiv__(x, y): def __idiv__(x, y):
x /= y x /= y
return x return x
def __ifloordiv__(x, y): def __ifloordiv__(x, y):
x //= y x //= y
return x return x
......
...@@ -26,11 +26,18 @@ from AccessControl.SecurityInfo import secureModule ...@@ -26,11 +26,18 @@ from AccessControl.SecurityInfo import secureModule
from AccessControl.SecurityInfo import allow_module from AccessControl.SecurityInfo import allow_module
from AccessControl.SecurityInfo import allow_class from AccessControl.SecurityInfo import allow_class
from AccessControl.SimpleObjectPolicies import allow_type from AccessControl.SimpleObjectPolicies import allow_type
from AccessControl.unauthorized import Unauthorized # XXX from AccessControl.unauthorized import Unauthorized
from AccessControl.ZopeGuards import full_write_guard from AccessControl.ZopeGuards import full_write_guard
from AccessControl.ZopeGuards import safe_builtins from AccessControl.ZopeGuards import safe_builtins
ModuleSecurityInfo('AccessControl').declarePublic('getSecurityManager') ModuleSecurityInfo('AccessControl').declarePublic('getSecurityManager')
# allow imports of utility_builtins
for name in ('string', 'math', 'random', 'sets'):
ModuleSecurityInfo(name).setDefaultAccess('allow')
ModuleSecurityInfo('DateTime').declarePublic('DateTime')
from AccessControl import DTML # XXX side effects? from AccessControl import DTML # XXX side effects?
del DTML del DTML
...@@ -42,6 +42,9 @@ class ModuleSecurityTests(unittest.TestCase): ...@@ -42,6 +42,9 @@ class ModuleSecurityTests(unittest.TestCase):
from AccessControl.ZopeGuards import guarded_import from AccessControl.ZopeGuards import guarded_import
guarded_import(module, fromlist=fromlist, level=level) guarded_import(module, fromlist=fromlist, level=level)
def test_unprotected_module(self):
self.assertUnauth('os', ())
def testPrivateModule(self): def testPrivateModule(self):
self.assertUnauth('AccessControl.tests.private_module', ()) self.assertUnauth('AccessControl.tests.private_module', ())
self.assertUnauth('AccessControl.tests.private_module', ('priv',)) self.assertUnauth('AccessControl.tests.private_module', ('priv',))
......
...@@ -761,10 +761,6 @@ print foo(**kw) ...@@ -761,10 +761,6 @@ print foo(**kw)
g['__name__'] = __name__ # so classes can be defined in the script g['__name__'] = __name__ # so classes can be defined in the script
return code, g return code, g
def testPythonRealAC(self):
code, its_globals = self._compile("actual_python.py")
exec code in its_globals
# Compile code in fname, as restricted Python. Return the # Compile code in fname, as restricted Python. Return the
# compiled code, and a safe globals dict for running it in. # compiled code, and a safe globals dict for running it in.
# fname is the string name of a Python file; it must be found # fname is the string name of a Python file; it must be found
......
...@@ -40,7 +40,7 @@ from DocumentTemplate.DT_Var import url_unquote_plus ...@@ -40,7 +40,7 @@ from DocumentTemplate.DT_Var import url_unquote_plus
from DocumentTemplate.DT_Var import restructured_text from DocumentTemplate.DT_Var import restructured_text
from ZPublisher.HTTPRequest import record from ZPublisher.HTTPRequest import record
security = ModuleSecurityInfo() security = ModuleSecurityInfo('Products.PythonScripts.standard')
security.declarePublic('special_formats', security.declarePublic('special_formats',
'whole_dollars', 'whole_dollars',
......
...@@ -131,9 +131,6 @@ class TestPythonScriptNoAq(PythonScriptTestBase): ...@@ -131,9 +131,6 @@ class TestPythonScriptNoAq(PythonScriptTestBase):
def testCollector2295(self): def testCollector2295(self):
res = self._newPS('if False:\n pass\n#hi') res = self._newPS('if False:\n pass\n#hi')
def testCollector2295(self):
res = self._newPS('if False:\n pass\n#hi')
def testReduce(self): def testReduce(self):
res = self._newPS('return reduce(lambda x, y: x + y, [1,3,5,7])')() res = self._newPS('return reduce(lambda x, y: x + y, [1,3,5,7])')()
self.assertEqual(res, 16) self.assertEqual(res, 16)
......
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