Log message for revision 113160: Merge the hannosch-dtml-vs-accesscontrol branch
Changed: A Zope/trunk/AC-vs-DTML-TODO.txt U Zope/trunk/src/AccessControl/DTML.py U Zope/trunk/src/AccessControl/ImplC.py U Zope/trunk/src/AccessControl/ImplPython.py U Zope/trunk/src/AccessControl/Implementation.py U Zope/trunk/src/AccessControl/Owned.py U Zope/trunk/src/AccessControl/PermissionMapping.py U Zope/trunk/src/AccessControl/Permissions.py U Zope/trunk/src/AccessControl/Role.py U Zope/trunk/src/AccessControl/SecurityInfo.py U Zope/trunk/src/AccessControl/SimpleObjectPolicies.py U Zope/trunk/src/AccessControl/User.py U Zope/trunk/src/AccessControl/__init__.py A Zope/trunk/src/AccessControl/class_init.py U Zope/trunk/src/AccessControl/metaconfigure.py D Zope/trunk/src/AccessControl/securitySuite/ U Zope/trunk/src/AccessControl/tests/testAcquisition.py U Zope/trunk/src/AccessControl/tests/testBindings.py U Zope/trunk/src/AccessControl/tests/testClassSecurityInfo.py D Zope/trunk/src/AccessControl/tests/testSecurity.py U Zope/trunk/src/AccessControl/tests/testZCML.py U Zope/trunk/src/AccessControl/tests/testZopeGuards.py U Zope/trunk/src/App/class_init.py U Zope/trunk/src/DocumentTemplate/DT_Util.py U Zope/trunk/src/DocumentTemplate/__init__.py A Zope/trunk/src/DocumentTemplate/permissions.py A Zope/trunk/src/DocumentTemplate/security.py U Zope/trunk/src/DocumentTemplate/sequence/__init__.py A Zope/trunk/src/DocumentTemplate/tests/testSecurity.py U Zope/trunk/src/Globals/__init__.py U Zope/trunk/src/OFS/DTMLDocument.py U Zope/trunk/src/OFS/DTMLMethod.py U Zope/trunk/src/OFS/FindSupport.py U Zope/trunk/src/Products/PageTemplates/ZRPythonExpr.py U Zope/trunk/src/Products/PythonScripts/standard.py U Zope/trunk/src/Products/ZCatalog/ZCatalog.py U Zope/trunk/src/Shared/DC/ZRDB/DA.py U Zope/trunk/src/Testing/ZopeTestCase/testFunctional.py -=- Copied: Zope/trunk/AC-vs-DTML-TODO.txt (from rev 113159, Zope/branches/hannosch-dtml-vs-accesscontrol/TODO.txt) =================================================================== --- Zope/trunk/AC-vs-DTML-TODO.txt (rev 0) +++ Zope/trunk/AC-vs-DTML-TODO.txt 2010-06-05 16:50:37 UTC (rev 113160) @@ -0,0 +1,71 @@ +Standalone AccessControl and DTML +================================= + +AccessControl +------------- + +- Acceptable dependencies (we can improve on that later): + + * zope.component + * zope.configuration + * zope.deferredimport + * zope.interface + * zope.publisher + * zope.schema + * zope.security + * zExceptions + * Acquisition + * ExtensionClass + * Persistence + * Record + * RestrictedPython + * ZODB3 + +- Remaining outside imports: + + * Products (in registerPermissions using it as a data container for + ``__ac_permissions__``) - this should use a global inside the module + inside AccessControl. + + * App (MessageDialog, DTMLFile, ...) - all need to go - redoing the UI is + hard. We probably need to move it into some other core part of Zope2, like + the App package, which could serve as a general dumping ground for ZMI + related stuff from "reusable" packages. + +- Test only dependencies: + + * OFS + * Products.PythonScripts + * Products.SiteErrorLog + * Testing + * transaction + * Zope2 + +DocumentTemplate +---------------- + +- TreeDisplay should be moved into the DocumentTemplate distribution, the two + depend on each other. + +- Acceptable dependencies (we can improve on that later): + + * zope.sequencesort + * zope.structuredtext + * AccessControl (once it is its own distribution) + * Acquisition + * ExtensionClass + * Missing + * RestrictedPython + * zExceptions + +- Remaining outside imports: + + * App (getConfiguration().structured_text_header_level) + * reStructuredText (HTML) - Both of these deal with format support and + configuration via zope.conf. The calls are localized to one function each. + Add an optional dependency on Zope2? Configure if it is available, + otherwise use some default? + +- Test only dependencies: + + * Products.PythonScripts Modified: Zope/trunk/src/AccessControl/DTML.py =================================================================== --- Zope/trunk/src/AccessControl/DTML.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/AccessControl/DTML.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -11,97 +11,11 @@ # ############################################################################## """Add security system support to Document Templates - -$Id$ """ -from DocumentTemplate import DT_Util -import SecurityManagement, string, math, random, sets -import DocumentTemplate.sequence -from ZopeGuards import safe_builtins +from zope.deferredimport import deprecated -# RestrictedDTML is inserted by AccessControl.Implementation. - - -# Allow access to unprotected attributes -DT_Util.TemplateDict.__allow_access_to_unprotected_subobjects__=1 -string.__allow_access_to_unprotected_subobjects__=1 -math.__allow_access_to_unprotected_subobjects__=1 -random.__allow_access_to_unprotected_subobjects__=1 -sets.__allow_access_to_unprotected_subobjects__=1 - - -DocumentTemplate.sequence.__allow_access_to_unprotected_subobjects__=1 - -# Add security testing capabilities - -class DTMLSecurityAPI: - """API for performing security checks in DTML using '_' methods. - """ - - def SecurityValidate(md, inst, parent, name, value): - """Validate access. - - Arguments: - - accessed -- the object that was being accessed - - container -- the object the value was found in - - name -- The name used to access the value - - value -- The value retrieved though the access. - - The arguments may be provided as keyword arguments. Some of these - arguments may be ommitted, however, the policy may reject access - in some cases when arguments are ommitted. It is best to provide - all the values possible. - """ - return (SecurityManagement - .getSecurityManager() - .validate(inst, parent, name, value) - ) - - def SecurityCheckPermission(md, permission, object): - """Check whether the security context allows the given permission on - the given object. - - Arguments: - - permission -- A permission name - - object -- The object being accessed according to the permission - """ - return (SecurityManagement - .getSecurityManager() - .checkPermission(permission, object) - ) - - def SecurityGetUser(md): - """Gen the current authenticated user""" - return (SecurityManagement - .getSecurityManager() - .getUser() - ) - - def SecurityCalledByExecutable(md): - """Return a boolean value indicating if this context was called - by an executable""" - r = (SecurityManagement - .getSecurityManager() - .calledByExecutable() - ) - if r > 0: return r-1 - return r - -for name, v in DTMLSecurityAPI.__dict__.items(): - if name[0] != '_': - setattr(DT_Util.TemplateDict, name, v) - -from types import FunctionType -for name, v in safe_builtins.items(): - if type(v) is FunctionType: - v = DT_Util.NotBindable(v) - if name.startswith('__'): - continue - setattr(DT_Util.TemplateDict, name, v) +deprecated("Please import from DocumentTemplate.security", + DTMLSecurityAPI = 'DocumentTemplate.security:DTMLSecurityAPI', + RestrictedDTML = 'DocumentTemplate.security:RestrictedDTML', +) Modified: Zope/trunk/src/AccessControl/ImplC.py =================================================================== --- Zope/trunk/src/AccessControl/ImplC.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/AccessControl/ImplC.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -18,7 +18,6 @@ from AccessControl.cAccessControl import PermissionRole from AccessControl.cAccessControl import imPermissionRole from AccessControl.cAccessControl import _what_not_even_god_should_do - from AccessControl.cAccessControl import RestrictedDTMLMixin from AccessControl.cAccessControl import aq_validate from AccessControl.cAccessControl import guarded_getattr from AccessControl.cAccessControl import setDefaultBehaviors @@ -31,15 +30,11 @@ # make sure a partial import doesn't pollute sys.modules del sys.modules[__name__] raise - -from AccessControl.ImplPython import RestrictedDTML + from AccessControl.ImplPython import SecurityManager from AccessControl.ImplPython import ZopeSecurityPolicy -class RestrictedDTML(RestrictedDTMLMixin, RestrictedDTML): - """A mix-in for derivatives of DT_String.String that adds Zope security.""" - class ZopeSecurityPolicy(cZopeSecurityPolicy, ZopeSecurityPolicy): """A security manager provides methods for checking access and managing executable context and policies Modified: Zope/trunk/src/AccessControl/ImplPython.py =================================================================== --- Zope/trunk/src/AccessControl/ImplPython.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/AccessControl/ImplPython.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -180,19 +180,6 @@ return len(v) -# AccessControl.DTML -# ------------------ - -class RestrictedDTML: - """A mix-in for derivatives of DT_String.String that adds Zope security.""" - - def guarded_getattr(self, *args): # ob, name [, default] - return guarded_getattr(*args) - - def guarded_getitem(self, ob, index): - return guarded_getitem(ob, index) - - # AccessControl.ZopeSecurityPolicy # -------------------------------- # Modified: Zope/trunk/src/AccessControl/Implementation.py =================================================================== --- Zope/trunk/src/AccessControl/Implementation.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/AccessControl/Implementation.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -75,8 +75,6 @@ _policy_names = { "AccessControl": ("setDefaultBehaviors", ), - "AccessControl.DTML": ("RestrictedDTML", - ), "AccessControl.PermissionRole": ("_what_not_even_god_should_do", "rolesForPermissionOn", "PermissionRole", Modified: Zope/trunk/src/AccessControl/Owned.py =================================================================== --- Zope/trunk/src/AccessControl/Owned.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/AccessControl/Owned.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -21,10 +21,10 @@ from Acquisition import aq_inner from Acquisition import aq_parent from App.special_dtml import DTMLFile -from App.class_init import InitializeClass from ExtensionClass import Base from zope.interface import implements +from AccessControl.class_init import InitializeClass from AccessControl.interfaces import IOwned from AccessControl.Permissions import view_management_screens from AccessControl.Permissions import take_ownership Modified: Zope/trunk/src/AccessControl/PermissionMapping.py =================================================================== --- Zope/trunk/src/AccessControl/PermissionMapping.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/AccessControl/PermissionMapping.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -22,10 +22,10 @@ from cgi import escape from Acquisition import ImplicitAcquisitionWrapper -from App.class_init import InitializeClass from ExtensionClass import Base from zope.interface import implements +from AccessControl.class_init import InitializeClass from AccessControl.interfaces import IPermissionMappingSupport from AccessControl.Owned import UnownableOwner from AccessControl.Permission import pname Modified: Zope/trunk/src/AccessControl/Permissions.py =================================================================== --- Zope/trunk/src/AccessControl/Permissions.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/AccessControl/Permissions.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -28,8 +28,6 @@ add_z_gadfly_database_connections='Add Z Gadfly Database Connections' add_zcatalogs='Add ZCatalogs' add_zope_tutorials='Add Zope Tutorials' -change_dtml_documents='Change DTML Documents' -change_dtml_methods='Change DTML Methods' change_database_connections='Change Database Connections' change_database_methods='Change Database Methods' change_external_methods='Change External Methods' @@ -67,3 +65,13 @@ webdav_access='WebDAV access' webdav_lock_items='WebDAV Lock items' webdav_unlock_items='WebDAV Unlock items' + + +from zope.deferredimport import deprecated + +new_loc = 'DocumentTemplate.permissions' + +deprecated("Please import from %s" % new_loc, + change_dtml_documents = '%s:change_dtml_documents' % new_loc, + change_dtml_methods = '%s:change_dtml_methods' % new_loc, +) Modified: Zope/trunk/src/AccessControl/Role.py =================================================================== --- Zope/trunk/src/AccessControl/Role.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/AccessControl/Role.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -22,13 +22,13 @@ from AccessControl import ClassSecurityInfo from AccessControl.SecurityManagement import newSecurityManager from AccessControl.Permissions import change_permissions -from App.class_init import InitializeClass from App.Dialogs import MessageDialog from App.special_dtml import DTMLFile from ExtensionClass import Base from PermissionMapping import RoleManager from zope.interface import implements +from AccessControl.class_init import InitializeClass from AccessControl.interfaces import IRoleManager from AccessControl.Permission import Permission from AccessControl.requestmethod import requestmethod Modified: Zope/trunk/src/AccessControl/SecurityInfo.py =================================================================== --- Zope/trunk/src/AccessControl/SecurityInfo.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/AccessControl/SecurityInfo.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -311,5 +311,5 @@ sec.declareObjectPublic() sec.setDefaultAccess(1) sec.apply(Class) - from App.class_init import InitializeClass + from AccessControl.class_init import InitializeClass InitializeClass(Class) Modified: Zope/trunk/src/AccessControl/SimpleObjectPolicies.py =================================================================== --- Zope/trunk/src/AccessControl/SimpleObjectPolicies.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/AccessControl/SimpleObjectPolicies.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -77,21 +77,6 @@ type(u''): 1, } -class _dummy_class: pass - -from DocumentTemplate.DT_Util import TemplateDict -# Temporarily create a DictInstance so that we can mark its type as -# being a key in the ContainerAssertions. -templateDict = TemplateDict() -try: - dictInstance = templateDict(dummy=1)[0] - if type(dictInstance) is not type(_dummy_class()): - ContainerAssertions[type(dictInstance)]=1 -except: - # Hmm, this may cause _() and _.namespace() to fail. - # What to do? - pass - Containers = ContainerAssertions.get def allow_type(Type, allowed=1): Modified: Zope/trunk/src/AccessControl/User.py =================================================================== --- Zope/trunk/src/AccessControl/User.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/AccessControl/User.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -24,12 +24,12 @@ from Acquisition import aq_parent from Acquisition import aq_inContextOf from Acquisition import Implicit -from App.class_init import InitializeClass from App.Management import Navigation from App.Management import Tabs from App.special_dtml import DTMLFile from App.Dialogs import MessageDialog from AccessControl import ClassSecurityInfo +from AccessControl.class_init import InitializeClass from AccessControl.Permissions import manage_users as ManageUsers from OFS.SimpleItem import Item from Persistence import Persistent Modified: Zope/trunk/src/AccessControl/__init__.py =================================================================== --- Zope/trunk/src/AccessControl/__init__.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/AccessControl/__init__.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -31,6 +31,3 @@ from AccessControl.ZopeGuards import safe_builtins ModuleSecurityInfo('AccessControl').declarePublic('getSecurityManager') - -from AccessControl import DTML # XXX side effects? -del DTML Copied: Zope/trunk/src/AccessControl/class_init.py (from rev 113159, Zope/branches/hannosch-dtml-vs-accesscontrol/src/AccessControl/class_init.py) =================================================================== --- Zope/trunk/src/AccessControl/class_init.py (rev 0) +++ Zope/trunk/src/AccessControl/class_init.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -0,0 +1,89 @@ +############################################################################## +# +# Copyright (c) 2002 Zope Foundation and Contributors. +# +# 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. +# +############################################################################## +"""Class initialization. + +$Id$ +""" + +import logging + +from AccessControl.Permission import ApplicationDefaultPermissions # BBB + +def InitializeClass(self): + from AccessControl.Permission import registerPermissions + from AccessControl.PermissionRole import PermissionRole + dict=self.__dict__ + have=dict.has_key + ft=type(InitializeClass) + dict_items=dict.items() + + for name, v in dict_items: + if getattr(v, '_need__name__', 0): + d = v.__dict__ + oldname = d.get('__name__', '') + if d.get('_implicit__name__', 0): + # Already supplied a name. + if name != oldname: + # Tried to implicitly assign a different name! + try: classname = '%s.%s' % ( + self.__module__, self.__name__) + except AttributeError: classname = `self` + logging.getLogger("Init").warning( + 'Ambiguous name for method of %s: %r != %r', + classname, d['__name__'], name) + else: + # Supply a name implicitly so that the method can + # find the security assertions on its container. + v._implicit__name__ = 1 + v.__name__ = name + if name=='manage' or name[:7]=='manage_': + name=name+'__roles__' + if not have(name): + setattr(self, name, ('Manager',)) + elif name=='manage' or name[:7]=='manage_' and type(v) is ft: + name=name+'__roles__' + if not have(name): + setattr(self, name, ('Manager',)) + + # Look for a SecurityInfo object on the class. If found, call its + # apply() method to generate __ac_permissions__ for the class. We + # delete the SecurityInfo from the class dict after it has been + # applied out of paranoia. + for key, value in dict_items: + if hasattr(value, '__security_info__'): + security_info=value + security_info.apply(self) + delattr(self, key) + break + + if self.__dict__.has_key('__ac_permissions__'): + registerPermissions(self.__ac_permissions__) + for acp in self.__ac_permissions__: + pname, mnames = acp[:2] + if len(acp) > 2: + roles = acp[2] + pr = PermissionRole(pname, roles) + else: + pr = PermissionRole(pname) + for mname in mnames: + setattr(self, mname+'__roles__', pr) + if (mname and mname not in ('context', 'request') and + not hasattr(self, mname)): + # don't complain about context or request, as they are + # frequently not available as class attributes + logging.getLogger("Init").warning( + "Class %s.%s has a security declaration for " + "nonexistent method %r", self.__module__, + self.__name__, mname) + +default__class_init__ = InitializeClass # BBB: old name Modified: Zope/trunk/src/AccessControl/metaconfigure.py =================================================================== --- Zope/trunk/src/AccessControl/metaconfigure.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/AccessControl/metaconfigure.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -14,8 +14,8 @@ import warnings from zope.security import metaconfigure +from AccessControl.class_init import InitializeClass from AccessControl.security import protectName -from App.class_init import InitializeClass class ClassDirective(metaconfigure.ClassDirective): Modified: Zope/trunk/src/AccessControl/tests/testAcquisition.py =================================================================== --- Zope/trunk/src/AccessControl/tests/testAcquisition.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/AccessControl/tests/testAcquisition.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -25,8 +25,8 @@ Zope2.startup() from OFS.SimpleItem import SimpleItem -from App.class_init import InitializeClass from AccessControl import ClassSecurityInfo +from AccessControl.class_init import InitializeClass from AccessControl.SecurityManagement import newSecurityManager from AccessControl.SecurityManagement import noSecurityManager from AccessControl.Permissions import view, view_management_screens Modified: Zope/trunk/src/AccessControl/tests/testBindings.py =================================================================== --- Zope/trunk/src/AccessControl/tests/testBindings.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/AccessControl/tests/testBindings.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -21,7 +21,7 @@ import transaction from Acquisition import Implicit from AccessControl import ClassSecurityInfo -from App.class_init import InitializeClass +from AccessControl.class_init import InitializeClass from OFS.ObjectManager import ObjectManager from OFS.Folder import Folder Modified: Zope/trunk/src/AccessControl/tests/testClassSecurityInfo.py =================================================================== --- Zope/trunk/src/AccessControl/tests/testClassSecurityInfo.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/AccessControl/tests/testClassSecurityInfo.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -28,7 +28,7 @@ # Test setting default roles for permissions. - from App.class_init import InitializeClass + from AccessControl.class_init import InitializeClass from ExtensionClass import Base ClassSecurityInfo = self._getTargetClass() Deleted: Zope/trunk/src/AccessControl/tests/testSecurity.py =================================================================== --- Zope/trunk/src/AccessControl/tests/testSecurity.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/AccessControl/tests/testSecurity.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -1,122 +0,0 @@ -############################################################################## -# -# Copyright (c) 2002 Zope Foundation and Contributors. -# -# 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 -# -############################################################################## -"""Document Template Tests -""" - -__rcs_id__='$Id$' -__version__='$Revision: 1.13 $'[11:-2] - -import os, sys, unittest - -import ZODB -from DocumentTemplate import HTML -from DocumentTemplate.tests.testDTML import DTMLTests -from Products.PythonScripts.standard import DTML -from AccessControl import User, Unauthorized -from ExtensionClass import Base - -class UnownedDTML(DTML): - def getOwner(self): - return None - -class SecurityTests (DTMLTests): - doc_class = UnownedDTML - unrestricted_doc_class = HTML - - def testNoImplicitAccess(self): - class person: - name='Jim' - - doc = self.doc_class( - '<dtml-with person>Hi, my name is ' - '<dtml-var name></dtml-with>') - try: - doc(person=person()) - except Unauthorized: - # Passed the test. - pass - else: - assert 0, 'Did not protect class instance' - - def testExprExplicitDeny(self): - class myclass (Base): - __roles__ = None # Public - somemethod__roles__ = () # Private - def somemethod(self): - return "This is a protected operation of public object" - - html = self.doc_class('<dtml-var expr="myinst.somemethod()">') - self.failUnlessRaises(Unauthorized, html, myinst=myclass()) - - def testSecurityInSyntax(self): - # Ensures syntax errors are thrown for an expr with restricted - # syntax. - expr = '<dtml-var expr="(lambda x, _read=(lambda ob:ob): x.y)(c)">' - try: - # This would be a security hole. - html = self.doc_class(expr) # It might compile here... - html() # or it might compile here. - except SyntaxError: - # Passed the test. - pass - else: - assert 0, 'Did not catch bad expr' - # Now be sure the syntax error occurred for security purposes. - html = self.unrestricted_doc_class(expr) - class c: - y = 10 - res = html(c=c) - assert res == '10', res - - def testNewDTMLBuiltins(self): - - NEW_BUILTINS_TEMPLATE = """ - <dtml-var expr="_.min([1,2])"> - <dtml-var expr="_.max([2,3])"> - <dtml-var expr="_.sum([1,2,3,4])"> - <dtml-var expr="_.hasattr(1, 'foo') and 'Yes' or 'No'"> - <dtml-var expr="_.None"> - <dtml-var expr="_.string.strip(' testing ')"> - <dtml-var expr="[x for x in (1, 2, 3)]"> - """ - - EXPECTED = ['1', '3', '10', 'No', 'None', 'testing', '[1, 2, 3]'] - - # - # XXX: these expressions seem like they should work, with - # the following ExPECTED, but they raise Unauthorized - # on the 'next' name. - # - #<dtml-var expr="_.iter([1,2,3]).next()"> - #<dtml-var expr="_.enumerate([1,2,3]).next()"> - # - #EXPECTED = ['1', '3', '10', '1', '(0, 1)'] - - template = self.doc_class(NEW_BUILTINS_TEMPLATE) - res = template() - lines = filter(None, [x.strip() for x in res.split('\n')]) - - self.assertEqual(lines, EXPECTED) - - # Note: we need more tests! - -def test_suite(): - suite = unittest.TestSuite() - suite.addTest( unittest.makeSuite( SecurityTests ) ) - return suite - -def main(): - unittest.TextTestRunner().run(test_suite()) - -if __name__ == '__main__': - main() Modified: Zope/trunk/src/AccessControl/tests/testZCML.py =================================================================== --- Zope/trunk/src/AccessControl/tests/testZCML.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/AccessControl/tests/testZCML.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -109,7 +109,7 @@ >>> from zope.configuration.xmlconfig import xmlconfig >>> xmlconfig(configure_zcml) - >>> from App.class_init import InitializeClass + >>> from AccessControl.class_init import InitializeClass >>> InitializeClass(Dummy2) Now we compare their access controls: Modified: Zope/trunk/src/AccessControl/tests/testZopeGuards.py =================================================================== --- Zope/trunk/src/AccessControl/tests/testZopeGuards.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/AccessControl/tests/testZopeGuards.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -583,9 +583,9 @@ def _getProtectedBaseClass(self): + from AccessControl.class_init import InitializeClass from AccessControl.SecurityInfo import ClassSecurityInfo from ExtensionClass import Base - from App.class_init import InitializeClass global _ProtectedBase if _ProtectedBase is None: Modified: Zope/trunk/src/App/class_init.py =================================================================== --- Zope/trunk/src/App/class_init.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/App/class_init.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -11,79 +11,9 @@ # ############################################################################## """Class initialization. - -$Id$ """ -import logging - -from AccessControl.Permission import ApplicationDefaultPermissions # BBB - -def InitializeClass(self): - from AccessControl.Permission import registerPermissions - from AccessControl.PermissionRole import PermissionRole - dict=self.__dict__ - have=dict.has_key - ft=type(InitializeClass) - dict_items=dict.items() - - for name, v in dict_items: - if getattr(v, '_need__name__', 0): - d = v.__dict__ - oldname = d.get('__name__', '') - if d.get('_implicit__name__', 0): - # Already supplied a name. - if name != oldname: - # Tried to implicitly assign a different name! - try: classname = '%s.%s' % ( - self.__module__, self.__name__) - except AttributeError: classname = `self` - logging.getLogger("Init").warning( - 'Ambiguous name for method of %s: %r != %r', - classname, d['__name__'], name) - else: - # Supply a name implicitly so that the method can - # find the security assertions on its container. - v._implicit__name__ = 1 - v.__name__ = name - if name=='manage' or name[:7]=='manage_': - name=name+'__roles__' - if not have(name): - setattr(self, name, ('Manager',)) - elif name=='manage' or name[:7]=='manage_' and type(v) is ft: - name=name+'__roles__' - if not have(name): - setattr(self, name, ('Manager',)) - - # Look for a SecurityInfo object on the class. If found, call its - # apply() method to generate __ac_permissions__ for the class. We - # delete the SecurityInfo from the class dict after it has been - # applied out of paranoia. - for key, value in dict_items: - if hasattr(value, '__security_info__'): - security_info=value - security_info.apply(self) - delattr(self, key) - break - - if self.__dict__.has_key('__ac_permissions__'): - registerPermissions(self.__ac_permissions__) - for acp in self.__ac_permissions__: - pname, mnames = acp[:2] - if len(acp) > 2: - roles = acp[2] - pr = PermissionRole(pname, roles) - else: - pr = PermissionRole(pname) - for mname in mnames: - setattr(self, mname+'__roles__', pr) - if (mname and mname not in ('context', 'request') and - not hasattr(self, mname)): - # don't complain about context or request, as they are - # frequently not available as class attributes - logging.getLogger("Init").warning( - "Class %s.%s has a security declaration for " - "nonexistent method %r", self.__module__, - self.__name__, mname) - +# BBB +from AccessControl.Permission import ApplicationDefaultPermissions +from AccessControl.class_init import InitializeClass default__class_init__ = InitializeClass # BBB: old name Modified: Zope/trunk/src/DocumentTemplate/DT_Util.py =================================================================== --- Zope/trunk/src/DocumentTemplate/DT_Util.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/DocumentTemplate/DT_Util.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -34,6 +34,10 @@ from AccessControl.tainted import TaintedString +if 'test' not in utility_builtins: + from RestrictedPython.Utilities import test + utility_builtins['test'] = test + test = utility_builtins['test'] # for backwards compatibility, dont remove! utility_builtins['sequence']= sequence @@ -111,6 +115,7 @@ return retval TemplateDict.string = StringModuleWrapper() +TemplateDict.__allow_access_to_unprotected_subobjects__ = 1 # The functions below are meant to bind to the TemplateDict. Modified: Zope/trunk/src/DocumentTemplate/__init__.py =================================================================== --- Zope/trunk/src/DocumentTemplate/__init__.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/DocumentTemplate/__init__.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -10,16 +10,16 @@ # FOR A PARTICULAR PURPOSE # ############################################################################## -__doc__='''Package wrapper for Document Template +"""Package wrapper for Document Template This wrapper allows the (now many) document template modules to be -segregated in a separate package. +segregated in a separate package.""" -$Id$''' -__version__='$Revision: 1.18 $'[11:-2] - from DocumentTemplate.DT_String import String, File from DocumentTemplate.DT_HTML import HTML, HTMLDefault, HTMLFile # Register the dtml-tree tag import TreeDisplay + +from DocumentTemplate import security # Side effects! +del security Copied: Zope/trunk/src/DocumentTemplate/permissions.py (from rev 113159, Zope/branches/hannosch-dtml-vs-accesscontrol/src/DocumentTemplate/permissions.py) =================================================================== --- Zope/trunk/src/DocumentTemplate/permissions.py (rev 0) +++ Zope/trunk/src/DocumentTemplate/permissions.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -0,0 +1,2 @@ +change_dtml_documents='Change DTML Documents' +change_dtml_methods='Change DTML Methods' Copied: Zope/trunk/src/DocumentTemplate/security.py (from rev 113159, Zope/branches/hannosch-dtml-vs-accesscontrol/src/DocumentTemplate/security.py) =================================================================== --- Zope/trunk/src/DocumentTemplate/security.py (rev 0) +++ Zope/trunk/src/DocumentTemplate/security.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -0,0 +1,148 @@ +############################################################################## +# +# Copyright (c) 2002 Zope Foundation and Contributors. +# +# 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 +# +############################################################################## +"""Add security system support to Document Templates +""" + +import string, math, random, sets + +# Allow access to unprotected attributes +string.__allow_access_to_unprotected_subobjects__=1 +math.__allow_access_to_unprotected_subobjects__=1 +random.__allow_access_to_unprotected_subobjects__=1 +sets.__allow_access_to_unprotected_subobjects__=1 + +# Setup RestrictedDTML + +from AccessControl.ImplPython import guarded_getattr +from AccessControl.ZopeGuards import guarded_getitem + +RestrictedDTML = None + +class BaseRestrictedDTML: + """A mix-in for derivatives of DT_String.String that adds Zope security.""" + + def guarded_getattr(self, *args): # ob, name [, default] + return guarded_getattr(*args) + + def guarded_getitem(self, ob, index): + return guarded_getitem(ob, index) + + +# This does not respect the security policy as set by AccessControl. Instead +# it only deals with the C module being compiled or not. +try: + from AccessControl.cAccessControl import RestrictedDTMLMixin +except ImportError: + RestrictedDTML = BaseRestrictedDTML +else: + class RestrictedDTML(RestrictedDTMLMixin, BaseRestrictedDTML): + """C version of RestrictedDTML.""" + +# Add security testing capabilities + +from AccessControl import SecurityManagement + +class DTMLSecurityAPI: + """API for performing security checks in DTML using '_' methods. + """ + + def SecurityValidate(md, inst, parent, name, value): + """Validate access. + + Arguments: + + accessed -- the object that was being accessed + + container -- the object the value was found in + + name -- The name used to access the value + + value -- The value retrieved though the access. + + The arguments may be provided as keyword arguments. Some of these + arguments may be ommitted, however, the policy may reject access + in some cases when arguments are ommitted. It is best to provide + all the values possible. + """ + return (SecurityManagement + .getSecurityManager() + .validate(inst, parent, name, value) + ) + + def SecurityCheckPermission(md, permission, object): + """Check whether the security context allows the given permission on + the given object. + + Arguments: + + permission -- A permission name + + object -- The object being accessed according to the permission + """ + return (SecurityManagement + .getSecurityManager() + .checkPermission(permission, object) + ) + + def SecurityGetUser(md): + """Gen the current authenticated user""" + return (SecurityManagement + .getSecurityManager() + .getUser() + ) + + def SecurityCalledByExecutable(md): + """Return a boolean value indicating if this context was called + by an executable""" + r = (SecurityManagement + .getSecurityManager() + .calledByExecutable() + ) + if r > 0: return r-1 + return r + + +from DocumentTemplate import DT_Util + +for name, v in DTMLSecurityAPI.__dict__.items(): + if name[0] != '_': + setattr(DT_Util.TemplateDict, name, v) + +from types import FunctionType +from AccessControl.ZopeGuards import safe_builtins + +for name, v in safe_builtins.items(): + if type(v) is FunctionType: + v = DT_Util.NotBindable(v) + if name.startswith('__'): + continue + setattr(DT_Util.TemplateDict, name, v) + + +# Temporarily create a DictInstance so that we can mark its type as +# being a key in the ContainerAssertions. + +from AccessControl.SimpleObjectPolicies import ContainerAssertions + +class _dummy_class: + pass + +templateDict = DT_Util.TemplateDict() +try: + dictInstance = templateDict(dummy=1)[0] + if type(dictInstance) is not type(_dummy_class()): + ContainerAssertions[type(dictInstance)]=1 +except: + # Hmm, this may cause _() and _.namespace() to fail. + # What to do? + pass Modified: Zope/trunk/src/DocumentTemplate/sequence/__init__.py =================================================================== --- Zope/trunk/src/DocumentTemplate/sequence/__init__.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/DocumentTemplate/sequence/__init__.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -11,5 +11,6 @@ # ############################################################################## +__allow_access_to_unprotected_subobjects__ = 1 from zope.sequencesort.ssort import * Copied: Zope/trunk/src/DocumentTemplate/tests/testSecurity.py (from rev 113159, Zope/branches/hannosch-dtml-vs-accesscontrol/src/DocumentTemplate/tests/testSecurity.py) =================================================================== --- Zope/trunk/src/DocumentTemplate/tests/testSecurity.py (rev 0) +++ Zope/trunk/src/DocumentTemplate/tests/testSecurity.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -0,0 +1,112 @@ +############################################################################## +# +# Copyright (c) 2002 Zope Foundation and Contributors. +# +# 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 +# +############################################################################## +"""Document Template Tests +""" + +import unittest + +from DocumentTemplate import HTML +from DocumentTemplate.tests.testDTML import DTMLTests +from Products.PythonScripts.standard import DTML +from AccessControl import Unauthorized +from ExtensionClass import Base + +class UnownedDTML(DTML): + def getOwner(self): + return None + +class SecurityTests (DTMLTests): + doc_class = UnownedDTML + unrestricted_doc_class = HTML + + def testNoImplicitAccess(self): + class person: + name='Jim' + + doc = self.doc_class( + '<dtml-with person>Hi, my name is ' + '<dtml-var name></dtml-with>') + try: + doc(person=person()) + except Unauthorized: + # Passed the test. + pass + else: + assert 0, 'Did not protect class instance' + + def testExprExplicitDeny(self): + class myclass (Base): + __roles__ = None # Public + somemethod__roles__ = () # Private + def somemethod(self): + return "This is a protected operation of public object" + + html = self.doc_class('<dtml-var expr="myinst.somemethod()">') + self.failUnlessRaises(Unauthorized, html, myinst=myclass()) + + def testSecurityInSyntax(self): + # Ensures syntax errors are thrown for an expr with restricted + # syntax. + expr = '<dtml-var expr="(lambda x, _read=(lambda ob:ob): x.y)(c)">' + try: + # This would be a security hole. + html = self.doc_class(expr) # It might compile here... + html() # or it might compile here. + except SyntaxError: + # Passed the test. + pass + else: + assert 0, 'Did not catch bad expr' + # Now be sure the syntax error occurred for security purposes. + html = self.unrestricted_doc_class(expr) + class c: + y = 10 + res = html(c=c) + assert res == '10', res + + def testNewDTMLBuiltins(self): + + NEW_BUILTINS_TEMPLATE = """ + <dtml-var expr="_.min([1,2])"> + <dtml-var expr="_.max([2,3])"> + <dtml-var expr="_.sum([1,2,3,4])"> + <dtml-var expr="_.hasattr(1, 'foo') and 'Yes' or 'No'"> + <dtml-var expr="_.None"> + <dtml-var expr="_.string.strip(' testing ')"> + <dtml-var expr="[x for x in (1, 2, 3)]"> + """ + + EXPECTED = ['1', '3', '10', 'No', 'None', 'testing', '[1, 2, 3]'] + + # + # XXX: these expressions seem like they should work, with + # the following ExPECTED, but they raise Unauthorized + # on the 'next' name. + # + #<dtml-var expr="_.iter([1,2,3]).next()"> + #<dtml-var expr="_.enumerate([1,2,3]).next()"> + # + #EXPECTED = ['1', '3', '10', '1', '(0, 1)'] + + template = self.doc_class(NEW_BUILTINS_TEMPLATE) + res = template() + lines = filter(None, [x.strip() for x in res.split('\n')]) + + self.assertEqual(lines, EXPECTED) + + # Note: we need more tests! + +def test_suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(SecurityTests)) + return suite Modified: Zope/trunk/src/Globals/__init__.py =================================================================== --- Zope/trunk/src/Globals/__init__.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/Globals/__init__.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -34,8 +34,8 @@ PersistentMapping = 'Persistence:PersistentMapping', ) -deprecated("import from App.class_init instead", - InitializeClass = 'App.class_init:InitializeClass', +deprecated("import from AccessControl.class_init instead", + InitializeClass = 'AccessControl.class_init:InitializeClass', ) deprecated("import from AccessControl.Permission instead", Modified: Zope/trunk/src/OFS/DTMLDocument.py =================================================================== --- Zope/trunk/src/OFS/DTMLDocument.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/OFS/DTMLDocument.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -15,11 +15,11 @@ from urllib import quote from AccessControl import getSecurityManager -from AccessControl.Permissions import change_dtml_methods -from AccessControl.Permissions import change_dtml_documents from App.class_init import InitializeClass from App.special_dtml import DTMLFile from App.special_dtml import HTML +from DocumentTemplate.permissions import change_dtml_methods +from DocumentTemplate.permissions import change_dtml_documents from OFS.DTMLMethod import decapitate from OFS.DTMLMethod import DTMLMethod from OFS.PropertyManager import PropertyManager Modified: Zope/trunk/src/OFS/DTMLMethod.py =================================================================== --- Zope/trunk/src/OFS/DTMLMethod.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/OFS/DTMLMethod.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -22,14 +22,14 @@ from App.special_dtml import HTML from DateTime.DateTime import DateTime from AccessControl import getSecurityManager -from AccessControl.Permissions import change_dtml_methods from AccessControl.Permissions import view_management_screens from AccessControl.Permissions import change_proxy_roles from AccessControl.Permissions import view as View from AccessControl.Permissions import ftp_access -from AccessControl.DTML import RestrictedDTML from AccessControl.requestmethod import requestmethod from AccessControl.tainted import TaintedString +from DocumentTemplate.permissions import change_dtml_methods +from DocumentTemplate.security import RestrictedDTML from OFS.Cache import Cacheable from OFS.History import Historical from OFS.History import html_diff Modified: Zope/trunk/src/OFS/FindSupport.py =================================================================== --- Zope/trunk/src/OFS/FindSupport.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/OFS/FindSupport.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -18,7 +18,6 @@ from string import translate from AccessControl import ClassSecurityInfo -from AccessControl.DTML import RestrictedDTML from AccessControl.Permission import name_trans from AccessControl.Permissions import view_management_screens from Acquisition import aq_base @@ -28,6 +27,7 @@ from DocumentTemplate.DT_Util import Eval from DocumentTemplate.DT_Util import InstanceDict from DocumentTemplate.DT_Util import TemplateDict +from DocumentTemplate.security import RestrictedDTML from ExtensionClass import Base from zope.interface import implements Modified: Zope/trunk/src/Products/PageTemplates/ZRPythonExpr.py =================================================================== --- Zope/trunk/src/Products/PageTemplates/ZRPythonExpr.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/Products/PageTemplates/ZRPythonExpr.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -59,7 +59,7 @@ return mod from DocumentTemplate.DT_Util import TemplateDict, InstanceDict -from AccessControl.DTML import RestrictedDTML +from DocumentTemplate.security import RestrictedDTML class Rtd(RestrictedDTML, TemplateDict): this = None Modified: Zope/trunk/src/Products/PythonScripts/standard.py =================================================================== --- Zope/trunk/src/Products/PythonScripts/standard.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/Products/PythonScripts/standard.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -21,7 +21,6 @@ from urllib import urlencode -from AccessControl.DTML import RestrictedDTML from AccessControl.SecurityInfo import ModuleSecurityInfo from AccessControl.SecurityManagement import getSecurityManager from App.special_dtml import HTML @@ -38,6 +37,7 @@ from DocumentTemplate.DT_Var import url_unquote from DocumentTemplate.DT_Var import url_unquote_plus from DocumentTemplate.DT_Var import restructured_text +from DocumentTemplate.security import RestrictedDTML from ZPublisher.HTTPRequest import record security = ModuleSecurityInfo() Modified: Zope/trunk/src/Products/ZCatalog/ZCatalog.py =================================================================== --- Zope/trunk/src/Products/ZCatalog/ZCatalog.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/Products/ZCatalog/ZCatalog.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -22,7 +22,6 @@ import urllib from warnings import warn -from AccessControl.DTML import RestrictedDTML from AccessControl.Permission import name_trans from AccessControl.Permissions import manage_zcatalog_entries from AccessControl.Permissions import manage_zcatalog_indexes @@ -36,6 +35,7 @@ from DocumentTemplate.DT_Util import InstanceDict from DocumentTemplate.DT_Util import TemplateDict from DocumentTemplate.DT_Util import Eval +from DocumentTemplate.security import RestrictedDTML from OFS.Folder import Folder from OFS.ObjectManager import ObjectManager from Persistence import Persistent Modified: Zope/trunk/src/Shared/DC/ZRDB/DA.py =================================================================== --- Zope/trunk/src/Shared/DC/ZRDB/DA.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/Shared/DC/ZRDB/DA.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -19,7 +19,6 @@ import sys from time import time -from AccessControl.DTML import RestrictedDTML from AccessControl.Permissions import change_database_methods from AccessControl.Permissions import use_database_methods from AccessControl.Permissions import view_management_screens @@ -32,6 +31,7 @@ from App.special_dtml import DTMLFile from DocumentTemplate import HTML from DocumentTemplate.html_quote import html_quote +from DocumentTemplate.security import RestrictedDTML from DateTime.DateTime import DateTime from ExtensionClass import Base from BTrees.OOBTree import OOBucket as Bucket Modified: Zope/trunk/src/Testing/ZopeTestCase/testFunctional.py =================================================================== --- Zope/trunk/src/Testing/ZopeTestCase/testFunctional.py 2010-06-05 16:40:38 UTC (rev 113159) +++ Zope/trunk/src/Testing/ZopeTestCase/testFunctional.py 2010-06-05 16:50:37 UTC (rev 113160) @@ -29,7 +29,7 @@ from AccessControl.Permissions import view from AccessControl.Permissions import manage_properties from AccessControl.Permissions import add_documents_images_and_files -from AccessControl.Permissions import change_dtml_documents +from DocumentTemplate.permissions import change_dtml_documents from StringIO import StringIO from urllib import urlencode _______________________________________________ Zope-Checkins maillist - Zope-Checkins@zope.org https://mail.zope.org/mailman/listinfo/zope-checkins