Commit 82d43c24 authored by Hanno Schlichting's avatar Hanno Schlichting

Merge the hannosch-dtml-vs-accesscontrol branch

parents 8e66586c 7bfeaa40
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
......@@ -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
# 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 zope.deferredimport import deprecated
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',
)
......@@ -18,7 +18,6 @@ try:
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 @@ except ImportError:
# 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
......
......@@ -180,19 +180,6 @@ class imPermissionRole(Base):
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
# --------------------------------
#
......
......@@ -75,8 +75,6 @@ _implementation_set = 0
_policy_names = {
"AccessControl": ("setDefaultBehaviors",
),
"AccessControl.DTML": ("RestrictedDTML",
),
"AccessControl.PermissionRole": ("_what_not_even_god_should_do",
"rolesForPermissionOn",
"PermissionRole",
......
......@@ -21,10 +21,10 @@ from Acquisition import aq_get
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
......
......@@ -22,10 +22,10 @@ $Id$
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
......
......@@ -28,8 +28,6 @@ add_vocabularies='Add Vocabularies'
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 @@ view_management_screens='View management screens'
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,
)
......@@ -22,13 +22,13 @@ from Acquisition import aq_get
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
......
......@@ -311,5 +311,5 @@ def allow_class(Class):
sec.declareObjectPublic()
sec.setDefaultAccess(1)
sec.apply(Class)
from App.class_init import InitializeClass
from AccessControl.class_init import InitializeClass
InitializeClass(Class)
......@@ -77,21 +77,6 @@ ContainerAssertions={
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):
......
......@@ -24,12 +24,12 @@ from Acquisition import aq_base
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
......
......@@ -31,6 +31,3 @@ from AccessControl.ZopeGuards import full_write_guard
from AccessControl.ZopeGuards import safe_builtins
ModuleSecurityInfo('AccessControl').declarePublic('getSecurityManager')
from AccessControl import DTML # XXX side effects?
del DTML
##############################################################################
#
# 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
......@@ -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):
......
Architecture of the Zope SecuritySuite
The base class of the suite is "SecurityBase" and contains
the basic function of perform tests for permissions, roles
and perform ZPublisher request:
- _checkPermission()
- _checkRoles()
- _request()
##############################################################################
#
# 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 ResultObject:
""" result object used for keeping results from the
ZPublisher.Zope() calls
$Id$
"""
def __str__(self,expected=-1,with_output=1):
s = '\n'
s+= '-'*78
s+= "\nRequest: %s" % self.request
s+= "\nUser: %s" % self.user
s+= "\nExpected: %s" % expected + " got: %s %s" % (self.code,self.return_text)
if with_output:
s+= "\nOutput:"
s+= self.output
s+= "\n"
return s
__repr__ = __str__
def __call__(self,expected=-1):
return self.__str__(expected)
##############################################################################
#
# 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
#
##############################################################################
import sys, re, unittest, cStringIO
import ZPublisher, ResultObject
import OFS.Application
import AccessControl.SecurityManagement
# Set up a publishable, non-ZODB Zope application.
app = OFS.Application.Application()
def index_html():
" "
return "This is index_html."
app.index_html = index_html # Will index_html ever go away? ;-)
class BoboApplication:
# OFS.Application has a __bobo_traverse__ that ZPublisher thinks
# it should use to find the "real" root of the application.
# This class gets around that.
def __bobo_traverse__(self, request, name=None):
return app
# ZPublisher will look for these vars.
bobo_application = BoboApplication()
zpublisher_validated_hook=AccessControl.SecurityManagement.newSecurityManager
__bobo_before__=AccessControl.SecurityManagement.noSecurityManager
class SecurityBase(unittest.TestCase) :
""" Base class for all security tests
$Id$
"""
status_regex = re.compile("Status: ([0-9]{1,4}) (.*)",re.I)\
################################################################
# print the object hierachy
################################################################
def _testHierarchy(self):
""" print all test objects, permissions and roles """
self._PrintTestEnvironment(root=self.root.test)
def _PrintTestEnvironment(self,root):
""" print recursive all objects """
print '....'*len(root.getPhysicalPath()),root.getId()
folderObjs = []
for id,obj in root.objectItems():
if obj.meta_type in ['Folder','TestFolder']:
folderObjs.append(obj)
else:
print ' '*(1+len(root.getPhysicalPath())),obj.getId(),
print getattr(obj,"__roles__",(None,))
for folder in folderObjs:
self._PrintTestEnvironment(folder)
################################################################
# Check functions for permissions, roles and friends
################################################################
def _checkPermission(self, user, hier, perm, expected):
""" permission check on an objects for a given user.
-- 'user' is a user object as returned from a user folder
-- 'hier' is the path to the object in the notation 'f1.f2.f3.obj'
-- 'perm' is a permission name
-- 'expected' is either 0 or 1
"""
s = "self.root.%s" % hier
obj = eval(s)
res = user.has_permission(perm,obj)
if res != expected:
raise AssertionError, \
self._perm_debug (s,perm,res,expected)
def _checkRoles(self,hier,expected_roles=()):
""" check roles for a given object.
-- 'hier' is the path to the object in the notation 'f1.f2.f3.obj'
-- 'expected_roles' is a sequence of expected roles
"""
s = "self.root.%s.__roles__" % hier
roles = eval(s)
same = 0
if roles is None or expected_roles is None:
if (roles is None or tuple(roles) == ('Anonymous',)) and (
expected_roles is None or
tuple(expected_roles) == ('Anonymous',)):
same = 1
else:
got = {}
for r in roles: got[r] = 1
expected = {}
for r in expected_roles: expected[r] = 1
if got == expected: # Dict compare does the Right Thing.
same = 1
if not same:
raise AssertionError, self._roles_debug(hier,roles,expected_roles)
def _checkRequest(self,*args,**kw):
""" perform a ZPublisher request """
expected_code = kw.get('expected',200)
del kw['expected']
res = apply(self._request,args,kw)
if expected_code != res.code:
raise AssertionError, \
self._request_debug(res,expected_code,args,kw)
################################################################
# Debugging helpers when raising AssertionError
################################################################
def _perm_debug(self, obj , perm, res, expected):
s+= 'Object: %s' % obj
s+= ', Permission: %s' % perm
s+= ', has permission: %s' % res
s+= ', expected: %s' % expected
return s
def _roles_debug(self,hier,got_roles,expected_roles):
s = 'Object: %s' % hier
s+= ', has roles: %s' % `got_roles`
s+= ', expected roles: %s' % `expected_roles`
return s
def _request_debug(self,res,expected,args,kw):
s = 'Args: %s' % str(args)
s+= ', KW: %s' % str(kw)
s+= '\n%s\n' % res.__str__(with_output=0,expected=expected)
return s
def _request(self,*args,**kw):
""" perform a Zope request """
io =cStringIO.StringIO()
kw['fp']=io
# Publish this module.
testargs = (__name__,) + args
real_stdout = sys.stdout
garbage_out = cStringIO.StringIO()
sys.stdout = garbage_out # Silence, ZPublisher!
try:
ZPublisher.test(*testargs,**kw)
finally:
sys.stdout = real_stdout
outp = io.getvalue()
mo = self.status_regex.search(outp)
code,txt = mo.groups()
res = ResultObject.ResultObject()
res.request = args
res.user = kw.get('u','')
res.code = int(code)
res.return_text = txt
res.output = outp
return res
##############################################################################
#
# 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
#
##############################################################################
######################################################################
# Set up unit testing framework
#
# The following code should be at the top of every test module:
#
# import os, sys
# execfile(os.path.join(sys.path[0], 'framework.py'))
#
# ...and the following at the bottom:
#
# framework()
# Find the Testing package
if not sys.modules.has_key('Testing'):
p0 = sys.path[0]
if p0 and __name__ == '__main__':
os.chdir(p0)
p0 = ''
p = d = os.path.abspath(os.curdir)
while d:
if os.path.isdir(os.path.join(p, 'Testing')):
sys.path[:1] = [p0, os.pardir, p]
break
p, d = os.path.split(p)
else:
print 'Unable to locate Testing package.'
sys.exit(1)
import Testing, unittest
execfile(os.path.join(os.path.split(Testing.__file__)[0], 'common.py'))
##############################################################################
#
# 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
#
##############################################################################
# $Id$
import unittest
from AccessControl.SecurityInfo import ClassSecurityInfo
from AccessControl.SecurityManagement import getSecurityManager
from AccessControl.User import nobody
from AccessControl.securitySuite import SecurityBase
from OFS.Folder import Folder
from OFS.SimpleItem import SimpleItem
from App.class_init import InitializeClass
# let's define some permissions first
MAGIC_PERMISSION1 = 'Magic Permission 1'
MAGIC_PERMISSION2 = 'Magic Permission 2'
##############################################################################
# TestObject class
##############################################################################
class TestObject(SimpleItem):
""" test object """
security = ClassSecurityInfo()
__allow_access_to_unprotected_subobjects__ = 0
public_attr = 1
_protected_attr = 2
def __init__(self,id):
self.id = id
security.declarePrivate("private_func")
def private_func(self):
""" private func """
return "i am private"
def manage_func(self):
""" should be protected by manager role """
return "i am your manager function"
security.declareProtected(MAGIC_PERMISSION2,"manage_func2")
def manage_func2(self):
""" should be protected by manager role """
return "i am your manager function2"
security.declareProtected(MAGIC_PERMISSION1,"protected_func")
def protected_func(self):
""" proteced func """
return "i am protected "
security.declarePublic("public_func")
def public_func(self):
""" public func """
return "i am public"
security.setPermissionDefault(MAGIC_PERMISSION1, ("Manager","Owner"))
security.setPermissionDefault(MAGIC_PERMISSION2, ("TestRole",))
InitializeClass(TestObject)
##############################################################################
# Testfolder class
##############################################################################
class TestFolder(Folder):
""" test class """
def __init__(self,id):
self.id = id
def getId(self): return self.id
meta_type = 'TestFolder'
security = ClassSecurityInfo()
InitializeClass(TestFolder)
##############################################################################
# User Class
##############################################################################
class User:
def __init__(self,username,password,roles):
self.username = username
self.password = password
self.roles = roles
def auth(self):
return "%s:%s" % (self.username,self.password)
def __str__(self):
return "User(%s:%s:%s)" % (self.username,self.password,self.roles)
__repr__ = __str__
USERS = (
User('user1','123',[]),
User('user2','123',[]),
User('owner','123',('Owner',)),
User('manager','123',('Manager',))
)
def getAuth(username):
for user in USERS:
if user.username==username:
return "%s:%s" % (user.username,user.password)
raise KeyError,"no such username: %" % username
class AVeryBasicSecurityTest(SecurityBase.SecurityBase):
################################################################
# set up the test hierachy of objects
################################################################
def setUp(self):
""" my setup """
self.root = SecurityBase.app
acl = self.root.acl_users
for user in USERS:
try: acl._delUsers( user.username )
except: pass
for user in USERS:
acl._addUser(user.username,user.password,user.password,
user.roles, [])
# try to remove old crap
if 'test' in self.root.objectIds():
self.root._delObject('test')
# setup Folder hierarchy
test = TestFolder('test')
f1 = TestFolder('f1')
f2 = TestFolder('f2')
f3 = TestFolder('f3')
obj = TestObject('obj3')
anonobj = TestObject('anonobj')
anonobj.__roles__ = ('Anonymous',)
self.root._setObject('test',test)
self.root.test._setObject('f1',f1)
self.root.test._setObject('f2',f2)
self.root.test.f1._setObject('anonobj',anonobj)
self.root.test.f2._setObject('f3',f3)
self.root.test.f2.f3._setObject('obj3',obj)
def testNobody(self):
""" check permissions for nobody user """
self._checkPermission(nobody,'test.f1', 'View',1)
self._checkPermission(nobody,'test.f2', 'View',1)
self._checkPermission(nobody,'test.f2.f3','View',1)
self._checkPermission(nobody,'test.f1', MAGIC_PERMISSION1, None)
self._checkPermission(nobody,'test.f2', MAGIC_PERMISSION1, None)
self._checkPermission(nobody,'test.f2.f3',MAGIC_PERMISSION1, None)
def testPermissionAccess(self):
""" check permission based access """
self._checkRoles('test.f2.f3.obj3.public_func', None)
self._checkRoles('test.f2.f3.obj3.protected_func', ('Manager','Owner'))
self._checkRoles('test.f2.f3.obj3.manage_func', ('Manager',))
self._checkRoles('test.f2.f3.obj3.private_func', ())
def testZPublisherAccess(self):
""" test access through ZPublisher """
_r = [
('/test/f1/', None, 200),
('/test/f2', None, 200),
('/test/f2/f3', None, 200),
('/test/f2/f3/obj3/public_func', None, 200),
('/test/f2/f3/obj3/protected_func', None, 401),
('/test/f2/f3/obj3/manage_func', None, 401),
('/test/f2/f3/obj3/private_func', None, 401),
('/test/f1/', getAuth('manager'), 200),
('/test/f2', getAuth('manager'), 200),
('/test/f2/f3', getAuth('manager'), 200),
('/test/f2/f3/obj3/public_func', getAuth('manager'), 200),
('/test/f2/f3/obj3/protected_func', getAuth('manager'), 200),
('/test/f2/f3/obj3/manage_func', getAuth('manager'), 200),
('/test/f2/f3/obj3/private_func', getAuth('manager'), 401),
('/test/f1/', getAuth('owner'), 200),
('/test/f2', getAuth('owner'), 200),
('/test/f2/f3', getAuth('owner'), 200),
('/test/f2/f3/obj3/public_func', getAuth('owner'), 200),
('/test/f2/f3/obj3/protected_func', getAuth('owner'), 200),
('/test/f2/f3/obj3/manage_func', getAuth('owner'), 401),
('/test/f2/f3/obj3/private_func', getAuth('owner'), 401),
]
for path,auth,expected in _r:
if auth:
res = self._checkRequest(path,u=auth,expected=expected)
else:
res = self._checkRequest(path,expected=expected)
def test_suite():
return unittest.makeSuite(AVeryBasicSecurityTest)
def main():
unittest.TextTestRunner().run(test_suite())
if __name__ == '__main__':
main()
......@@ -25,8 +25,8 @@ import Zope2
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
......
......@@ -21,7 +21,7 @@ import ZODB
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
......
......@@ -28,7 +28,7 @@ class ClassSecurityInfoTests(unittest.TestCase):
# 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()
......
......@@ -109,7 +109,7 @@ def test_security_equivalence():
>>> 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:
......
......@@ -583,9 +583,9 @@ class TestActualPython(GuardTestCase):
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:
......
......@@ -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
......@@ -34,6 +34,10 @@ from RestrictedPython.Eval import RestrictionCapableEval
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 @@ class StringFunctionWrapper:
return retval
TemplateDict.string = StringModuleWrapper()
TemplateDict.__allow_access_to_unprotected_subobjects__ = 1
# The functions below are meant to bind to the TemplateDict.
......
......@@ -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.
$Id$'''
__version__='$Revision: 1.18 $'[11:-2]
segregated in a separate package."""
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
change_dtml_documents='Change DTML Documents'
change_dtml_methods='Change DTML Methods'
##############################################################################
#
# 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
......@@ -11,5 +11,6 @@
#
##############################################################################
__allow_access_to_unprotected_subobjects__ = 1
from zope.sequencesort.ssort import *
......@@ -13,16 +13,12 @@
"""Document Template Tests
"""
__rcs_id__='$Id$'
__version__='$Revision: 1.13 $'[11:-2]
import unittest
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 AccessControl import Unauthorized
from ExtensionClass import Base
class UnownedDTML(DTML):
......@@ -112,11 +108,5 @@ class SecurityTests (DTMLTests):
def test_suite():
suite = unittest.TestSuite()
suite.addTest( unittest.makeSuite( SecurityTests ) )
suite.addTest(unittest.makeSuite(SecurityTests))
return suite
def main():
unittest.TextTestRunner().run(test_suite())
if __name__ == '__main__':
main()
......@@ -34,8 +34,8 @@ deprecated("import from Persistence instead",
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",
......
......@@ -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
......
......@@ -22,14 +22,14 @@ from App.special_dtml import DTMLFile
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
......
......@@ -18,7 +18,6 @@ $Id$
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 DateTime.DateTime import DateTime
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
......
......@@ -59,7 +59,7 @@ class _SecureModuleImporter:
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
......
......@@ -21,7 +21,6 @@ __version__='$Revision: 1.14 $'[11:-2]
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 thousands_commas
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()
......
......@@ -22,7 +22,6 @@ import time
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 DateTime.DateTime import DateTime
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
......
......@@ -19,7 +19,6 @@ import string
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.Extensions import getBrain
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
......
......@@ -29,7 +29,7 @@ from AccessControl import getSecurityManager
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
......
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