Commit 89b1075e authored by Shane Hathaway's avatar Shane Hathaway

- Merged cAccessControl-review-branch.

- Made some corrections to the DTML tests, which aren't currently working
in testrunner but work when run directly. ??
parent 9f506076
......@@ -33,7 +33,7 @@
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
$Id: Acquisition.h,v 1.1 2001/07/03 19:38:20 matt Exp $
$Id: Acquisition.h,v 1.2 2001/10/19 15:12:24 shane Exp $
If you have questions regarding this software,
contact:
......@@ -77,15 +77,13 @@ typedef struct {
static ACQUISITIONCAPI *AcquisitionCAPI = NULL;
#define aq_init() { \
PyObject *module; \
PyObject *api; \
if ((module = PyImport_ImportModule("Acquisition")) == NULL) \
Py_FatalError("Acquisition CAPI failed to load Acquisition"); \
if ((api = PyObject_GetAttrString(module,"AcquisitionCAPI")) \
== NULL) Py_FatalError("Acquisition CAPI failed to load AcquistionCAPI"); \
Py_DECREF(module); \
AcquisitionCAPI = PyCObject_AsVoidPtr(api); \
Py_DECREF(api); \
PyObject *module; \
PyObject *api; \
if (! (module = PyImport_ImportModule("Acquisition"))) return; \
if (! (api = PyObject_GetAttrString(module,"AcquisitionCAPI"))) return; \
Py_DECREF(module); \
AcquisitionCAPI = PyCObject_AsVoidPtr(api); \
Py_DECREF(api); \
}
......
......@@ -85,19 +85,139 @@
__doc__='''Objects that implement Permission-based roles.
$Id: PermissionRole.py,v 1.11 2001/10/17 22:01:43 tseaver Exp $'''
__version__='$Revision: 1.11 $'[11:-2]
if 0: # cAccessControl is not working
import cAccessControl
rolesForPermissionOn=cAccessControl.rolesForPermissionOn
PermissionRole=cAccessControl.PermissionRole
imPermissionRole=cAccessControl.imPermissionRole
_what_not_even_god_should_do= cAccessControl._what_not_even_god_should_do
$Id: PermissionRole.py,v 1.12 2001/10/19 15:12:25 shane Exp $'''
__version__='$Revision: 1.12 $'[11:-2]
_use_python_impl = 0
import os
if os.environ.get("ZOPE_SECURITY_POLICY", None) == "PYTHON":
_use_python_impl = 1
else:
import pPermissionRole
from pPermissionRole import rolesForPermissionOn, PermissionRole
from pPermissionRole import imPermissionRole, _what_not_even_god_should_do
try:
# C Optimization:
from cAccessControl import rolesForPermissionOn, \
PermissionRole, imPermissionRole, _what_not_even_god_should_do
except ImportError:
# Fall back to Python implementation.
_use_python_impl = 1
if _use_python_impl:
import sys
from ExtensionClass import Base
import string
name_trans=filter(lambda c, an=string.letters+string.digits+'_': c not in an,
map(chr,range(256)))
name_trans=string.maketrans(string.join(name_trans,''), '_'*len(name_trans))
def rolesForPermissionOn(perm, object, default=('Manager',)):
"""Return the roles that have the given permission on the given object
"""
im=imPermissionRole()
im._p='_'+string.translate(perm, name_trans)+"_Permission"
im._d=default
return im.__of__(object)
class PermissionRole(Base):
"""Implement permission-based roles.
Under normal circumstances, our __of__ method will be
called with an unwrapped object. The result will then be called
with a wrapped object, if the original object was wrapped.
To deal with this, we have to create an intermediate object.
"""
def __init__(self, name, default=('Manager',)):
self.__name__=name
self._p='_'+string.translate(name,name_trans)+"_Permission"
self._d=default
def __of__(self, parent, None=None, getattr=getattr):
r=imPermissionRole()
r._p=self._p
r._pa=parent
r._d=self._d
p=getattr(parent, 'aq_inner', None)
if p is not None:
return r.__of__(p)
else:
return r
# This is used when a permission maps explicitly to no permission.
_what_not_even_god_should_do=[]
class imPermissionRole(Base):
"""Implement permission-based roles
"""
def __of__(self, parent,tt=type(()),st=type(''),getattr=getattr,None=None):
obj=parent
n=self._p
r=None
while 1:
if hasattr(obj,n):
roles=getattr(obj, n)
if roles is None: return 'Anonymous',
t=type(roles)
if t is tt:
# If we get a tuple, then we don't acquire
if r is None: return roles
return r+list(roles)
if t is st:
# We found roles set to a name. Start over
# with the new permission name. If the permission
# name is '', then treat as private!
if roles:
if roles != n:
n=roles
# If we find a name that is the same as the
# current name, we just ignore it.
roles=None
else:
return _what_not_even_god_should_do
elif roles:
if r is None: r=list(roles)
else: r=r+list(roles)
obj=getattr(obj, 'aq_inner', None)
if obj is None: break
obj=obj.aq_parent
if r is None: r=self._d
return r
# The following methods are needed in the unlikely case that an unwrapped
# object is accessed:
def __getitem__(self, i):
try:
v=self._v
except:
v=self._v=self.__of__(self._pa)
del self._pa
return v[i]
def __len__(self):
try:
v=self._v
except:
v=self._v=self.__of__(self._pa)
del self._pa
return len(v)
##############################################################################
# Test functions:
......
......@@ -85,8 +85,8 @@
__doc__='''short description
$Id: SecurityManager.py,v 1.6 2001/10/01 21:03:15 matt Exp $'''
__version__='$Revision: 1.6 $'[11:-2]
$Id: SecurityManager.py,v 1.7 2001/10/19 15:12:25 shane Exp $'''
__version__='$Revision: 1.7 $'[11:-2]
import ZopeSecurityPolicy, os, string
......@@ -145,8 +145,12 @@ class SecurityManager:
"""
policy=self._policy
if policy is None: policy=_defaultPolicy
return policy.validate(accessed, container, name, value,
self._context, roles)
if roles is _noroles:
return policy.validate(accessed, container, name, value,
self._context)
else:
return policy.validate(accessed, container, name, value,
self._context, roles)
def DTMLValidate(self, accessed=None, container=None, name=None,
value=None,md=None):
......@@ -175,15 +179,19 @@ class SecurityManager:
policy=self._policy
if policy is None: policy=_defaultPolicy
return policy.validate(accessed, container, name, value,
self._context, _noroles)
self._context)
def validateValue(self, value, roles=_noroles):
"""Convenience for common case of simple value validation.
"""
policy=self._policy
if policy is None: policy=_defaultPolicy
return policy.validate(None, None, None, value,
self._context, roles)
if roles is _noroles:
return policy.validate(None, None, None, value,
self._context)
else:
return policy.validate(None, None, None, value,
self._context, roles)
def checkPermission(self, permission, object):
"""Check whether the security context allows the given permission on
......
......@@ -84,7 +84,7 @@
##############################################################################
"""Access control package"""
__version__='$Revision: 1.159 $'[11:-2]
__version__='$Revision: 1.160 $'[11:-2]
import Globals, socket, SpecialUsers,re
import os
......@@ -98,7 +98,8 @@ from App.ImageFile import ImageFile
from Role import RoleManager, DEFAULTMAXLISTUSERS
from PermissionRole import _what_not_even_god_should_do, rolesForPermissionOn
import AuthEncoding
from AccessControl import getSecurityManager, Unauthorized
from AccessControl import getSecurityManager
from zExceptions import Unauthorized
from AccessControl.SecurityManagement import newSecurityManager
from AccessControl.SecurityManagement import noSecurityManager
from AccessControl.ZopeSecurityPolicy import _noroles
......
......@@ -83,7 +83,7 @@
#
##############################################################################
__version__='$Revision: 1.6 $'[11:-2]
__version__='$Revision: 1.7 $'[11:-2]
from RestrictedPython.Guards import safe_builtins, _full_read_guard, \
full_write_guard
......@@ -91,8 +91,7 @@ from RestrictedPython.Utilities import utility_builtins
from SecurityManagement import getSecurityManager
from SecurityInfo import secureModule
from SimpleObjectPolicies import Containers
Unauthorized = 'Unauthorized'
from zExceptions import Unauthorized
_marker = [] # Create a new marker object.
......
......@@ -83,7 +83,7 @@
#
##############################################################################
Unauthorized = 'Unauthorized'
from unauthorized import Unauthorized
import DTML
del DTML
......
This diff is collapsed.
#
from SimpleObjectPolicies import _noroles
import cAccessControl
ZopeSecurityPolicy = cAccessControl.ZopeSecurityPolicy
......@@ -82,69 +82,25 @@
# attributions are listed in the accompanying credits file.
#
##############################################################################
__doc__='''Objects that implement Permission-based roles.
"""Access control exceptions
"""
import zExceptions
$Id: cPermissionRole.py,v 1.1 2001/08/08 15:57:49 matt Exp $'''
__version__='$Revision: 1.1 $'[11:-2]
class Unauthorized(zExceptions.Unauthorized):
def getValueName(self):
v=self.value
n=getattr(v, 'getId', v)
if n is v: n=getattr(v, 'id', v)
if n is v: n=getattr(v, '__name__', v)
if n is not v:
if callable(n):
try: n = n()
except TypeError: pass
return n
import cAccessControl
rolesForPermissionOn=cAccessControl.rolesForPermissionOn
PermissionRole=cAccessControl.PermissionRole
imPermisionRole=cAccessControl.imPermissionRole
_what_not_even_god_should_do= cAccessControl._what_not_even_god_should_do
##############################################################################
# Test functions:
#
def main():
# The "main" program for this module
import sys
sys.path.append('/projects/_/ExtensionClass')
from Acquisition import Implicit
class I(Implicit):
x__roles__=PermissionRole('x')
y__roles__=PermissionRole('y')
z__roles__=PermissionRole('z')
def x(self): pass
def y(self): pass
def z(self): pass
a=I()
a.b=I()
a.b.c=I()
a.q=I()
a.q._x_Permission=('foo',)
a._y_Permission=('bar',)
a._z_Permission=('zee',)
a.b.c._y_Permission=('Manage',)
a.b._z_Permission=['also']
print a.x.__roles__, list(a.x.__roles__)
print a.b.x.__roles__
print a.b.c.x.__roles__
print a.q.x.__roles__
print a.b.q.x.__roles__
print a.b.c.q.x.__roles__
print
print a.y.__roles__, list(a.y.__roles__)
print a.b.y.__roles__
print a.b.c.y.__roles__
print a.q.y.__roles__
print a.b.q.y.__roles__
print a.b.c.q.y.__roles__
print
print a.z.__roles__, list(a.z.__roles__)
print a.b.z.__roles__
print a.b.c.z.__roles__
print a.q.z.__roles__
print a.b.q.z.__roles__
print a.b.c.q.z.__roles__
print
c = getattr(v, '__class__', type(v))
c = getattr(c, '__name__', 'object')
return "a particular %s" % c
......@@ -85,15 +85,15 @@
"""Standard management interface support
$Id: Management.py,v 1.50 2001/09/04 16:50:48 shane Exp $"""
$Id: Management.py,v 1.51 2001/10/19 15:12:25 shane Exp $"""
__version__='$Revision: 1.50 $'[11:-2]
__version__='$Revision: 1.51 $'[11:-2]
import sys, Globals, ExtensionClass, urllib
from Dialogs import MessageDialog
from Globals import DTMLFile, HTMLFile
from string import split, join, find
from AccessControl import getSecurityManager
from AccessControl import getSecurityManager, Unauthorized
class Tabs(ExtensionClass.Base):
"""Mix-in provides management folder tab support."""
......@@ -145,8 +145,8 @@ class Tabs(ExtensionClass.Base):
m=options[0]['action']
if m=='manage_workspace': raise TypeError
except:
raise 'Unauthorized', (
'You are not authorized to view this object.<p>')
raise Unauthorized, (
'You are not authorized to view this object.')
if find(m,'/'):
raise 'Redirect', (
......
......@@ -118,6 +118,7 @@ from Permission import PermissionManager
import ZClasses, ZClasses.ZClass
from HelpSys.HelpSys import ProductHelp
import RefreshFuncs
from AccessControl import Unauthorized
class ProductFolder(Folder):
......@@ -447,7 +448,7 @@ class Product(Folder, PermissionManager):
Attempts to perform a refresh operation.
'''
if self._readRefreshTxt() is None:
raise 'Unauthorized', 'refresh.txt not found'
raise Unauthorized, 'refresh.txt not found'
message = None
if RefreshFuncs.performFullRefresh(self._p_jar, self.id):
from ZODB import Connection
......@@ -463,7 +464,7 @@ class Product(Folder, PermissionManager):
Changes the auto refresh flag for this product.
'''
if self._readRefreshTxt() is None:
raise 'Unauthorized', 'refresh.txt not created'
raise Unauthorized, 'refresh.txt not created'
RefreshFuncs.enableAutoRefresh(self._p_jar, self.id, enable)
if enable:
message = 'Enabled auto refresh.'
......@@ -477,7 +478,7 @@ class Product(Folder, PermissionManager):
Selects which products to refresh simultaneously.
'''
if self._readRefreshTxt() is None:
raise 'Unauthorized', 'refresh.txt not created'
raise Unauthorized, 'refresh.txt not created'
RefreshFuncs.setDependentProducts(self._p_jar, self.id, selections)
if REQUEST is not None:
return self.manage_refresh(REQUEST)
......
......@@ -82,8 +82,8 @@
# attributions are listed in the accompanying credits file.
#
##############################################################################
'''$Id: DT_Util.py,v 1.83 2001/09/04 13:46:43 evan Exp $'''
__version__='$Revision: 1.83 $'[11:-2]
'''$Id: DT_Util.py,v 1.84 2001/10/19 15:12:26 shane Exp $'''
__version__='$Revision: 1.84 $'[11:-2]
import re, os
from html_quote import html_quote # for import by other modules, dont remove!
......@@ -98,7 +98,7 @@ LIMITED_BUILTINS = 1
str=__builtins__['str'] # Waaaaa, waaaaaaaa needed for pickling waaaaa
ParseError='Document Template Parse Error'
ValidationError='Unauthorized'
from zExceptions import Unauthorized as ValidationError
def int_param(params,md,name,default=0, st=type('')):
try: v=params[name]
......
......@@ -85,19 +85,16 @@
"""Document Template Tests
"""
__rcs_id__='$Id: testDTML.py,v 1.6 2001/07/02 16:30:46 shane Exp $'
__version__='$Revision: 1.6 $'[11:-2]
__rcs_id__='$Id: testDTML.py,v 1.7 2001/10/19 15:12:26 shane Exp $'
__version__='$Revision: 1.7 $'[11:-2]
import sys, os
import unittest
if __name__=='__main__':
sys.path.append(os.path.join(os.pardir, os.pardir))
here = os.curdir
else:
from DocumentTemplate import tests
from App.Common import package_home
here = package_home(tests.__dict__)
here = os.path.split(__file__)[0]
def read_file(name):
f = open(os.path.join(here, name), 'rb')
......@@ -122,7 +119,7 @@ class DTMLTests (unittest.TestCase):
doc_class = HTML
def checkBatchingEtc(self):
def testBatchingEtc(self):
def item(key,**kw): return (key,kw)
def item2(key,**kw): return kw
......@@ -239,7 +236,7 @@ class DTMLTests (unittest.TestCase):
expected = read_file('dealers.out')
assert res == expected, res
def checkSequenceSummaries(self):
def testSequenceSummaries(self):
def d(**kw): return kw
data=(d(name='jim', age=38),
# d(name='kak', age=40),
......@@ -274,7 +271,7 @@ class DTMLTests (unittest.TestCase):
'median=5 mean=12.5 s.d.=17')
assert res == expected, res
def checkDTMLDateFormatting(self):
def testDTMLDateFormatting(self):
import DateTime
html = self.doc_class(
"<dtml-var name capitalize spacify> is "
......@@ -285,13 +282,13 @@ class DTMLTests (unittest.TestCase):
expected = 'Christmas day is 1995/12/25'
assert res == expected, res
def checkSimpleString(self):
def testSimpleString(self):
dt = String('%(name)s')
res = dt(name='Chris')
expected = 'Chris'
assert res == expected, res
def checkStringDateFormatting(self):
def testStringDateFormatting(self):
import DateTime
html = String("%(name capitalize spacify)s is "
"%(date fmt=year)s/%(date fmt=month)s/%(date fmt=day)s")
......@@ -300,7 +297,7 @@ class DTMLTests (unittest.TestCase):
expected = 'The date is 2001/4/27'
assert res == expected, res
def checkSequence1(self):
def testSequence1(self):
html=self.doc_class(
'<dtml-in spam><dtml-in sequence-item><dtml-var sequence-item> '
'</dtml-in sequence-item></dtml-in spam>')
......@@ -308,7 +305,7 @@ class DTMLTests (unittest.TestCase):
res = html(spam=[[1,2,3],[4,5,6]])
assert res == expected, res
def checkSequence2(self):
def testSequence2(self):
html=self.doc_class(
'<dtml-in spam><dtml-in sequence-item><dtml-var sequence-item>-'
'</dtml-in sequence-item></dtml-in spam>')
......@@ -316,14 +313,14 @@ class DTMLTests (unittest.TestCase):
res = html(spam=[[1,2,3],[4,5,6]])
assert res == expected, res
def checkNull(self):
def testNull(self):
html=self.doc_class('<dtml-var spam fmt="$%.2f bobs your uncle" '
'null="spam%eggs!|">')
expected = '$42.00 bobs your unclespam%eggs!|'
res = html(spam=42) + html(spam=None)
assert res == expected, res
def check_fmt(self):
def test_fmt(self):
html=self.doc_class(
"""
<dtml-var spam>
......@@ -369,7 +366,7 @@ foo bar
spam='<a href="spam">\nfoo bar')
assert res == expected, res
def checkPropogatedError(self):
def testPropogatedError(self):
class foo:
def __len__(self): return 9
......@@ -408,7 +405,7 @@ foo bar
else:
assert 0, 'Puke error not propogated'
def checkRenderCallable(self):
def testRenderCallable(self):
"Test automatic rendering of callable objects"
class C (Base):
__allow_access_to_unprotected_subobjects__ = 1
......@@ -433,7 +430,7 @@ foo bar
<dtml-var expr="_.render(i.h2)">''')(i=C())
assert res == expected, res
def checkWith(self):
def testWith(self):
class person:
__allow_access_to_unprotected_subobjects__ = 1
name='Jim'
......@@ -448,7 +445,7 @@ foo bar
'cm.</dtml-with>')(person=person)
assert res == expected, res
def checkRaise(self):
def testRaise(self):
try:
res = self.doc_class(
"<dtml-raise IndexError>success!</dtml-raise>")()
......@@ -457,7 +454,7 @@ foo bar
assert str(res) == 'success!', `res`
def checkBasicHTMLIn(self):
def testBasicHTMLIn(self):
data=(
d(name='jim', age=39),
d(name='kak', age=29),
......@@ -481,7 +478,7 @@ foo bar
result = self.doc_class(html)(data=data)
assert result == expected, result
def checkBasicHTMLIn2(self):
def testBasicHTMLIn2(self):
xxx=(D(name=1), D(name=2), D(name=3))
html = """
<!--#in xxx-->
......@@ -496,7 +493,7 @@ foo bar
result = self.doc_class(html)(xxx=xxx)
assert result == expected, result
def checkBasicHTMLIn3(self):
def testBasicHTMLIn3(self):
ns = {'prop_ids': ('title', 'id'), 'title': 'good', 'id': 'times'}
html = """:<dtml-in prop_ids><dtml-var sequence-item>=<dtml-var
expr="_[_['sequence-item']]">:</dtml-in>"""
......@@ -505,7 +502,7 @@ foo bar
assert result == expected, result
def checkHTMLInElse(self):
def testHTMLInElse(self):
xxx=(D(name=1), D(name=2), D(name=3))
html="""
<!--#in data mapping-->
......@@ -524,7 +521,7 @@ foo bar
result = self.doc_class(html)(xxx=xxx, data={})
assert result == expected, result
def checkBasicStringIn(self):
def testBasicStringIn(self):
data=(
d(name='jim', age=39),
d(name='kak', age=29),
......@@ -548,22 +545,12 @@ foo bar
assert expected == result, result
def test_suite():
return unittest.makeSuite(DTMLTests, 'check')
suite = unittest.TestSuite()
suite.addTest( unittest.makeSuite( DTMLTests ) )
return suite
def main():
alltests = test_suite()
runner = unittest.TextTestRunner()
runner.run(alltests)
unittest.TextTestRunner().run(test_suite())
def debug():
test_suite().debug()
def pdebug():
import pdb
pdb.run('debug()')
if __name__=='__main__':
if len(sys.argv) > 1:
globals()[sys.argv[1]]()
else:
main()
if __name__ == '__main__':
main()
......@@ -84,9 +84,9 @@
##############################################################################
__doc__="""Cacheable object and cache management base classes.
$Id: Cache.py,v 1.6 2001/02/08 15:24:16 shane Exp $"""
$Id: Cache.py,v 1.7 2001/10/19 15:12:26 shane Exp $"""
__version__='$Revision: 1.6 $'[11:-2]
__version__='$Revision: 1.7 $'[11:-2]
import time, sys
from string import join
......@@ -96,6 +96,7 @@ from Acquisition import aq_get, aq_acquire, aq_inner, aq_parent, aq_base
from zLOG import LOG, WARNING
from AccessControl import getSecurityManager
from AccessControl.Role import _isBeingUsedAsAMethod
from AccessControl import Unauthorized
ZCM_MANAGERS = '__ZCacheManager_ids__'
......@@ -585,7 +586,7 @@ class CacheManager:
path = key[10:]
ob = parent.restrictedTraverse(path)
if not sm.checkPermission('Change cache settings', ob):
raise 'Unauthorized'
raise Unauthorized
if not isCacheable(ob):
# Not a cacheable object.
continue
......
......@@ -83,7 +83,7 @@
#
##############################################################################
__doc__="""Copy interface"""
__version__='$Revision: 1.74 $'[11:-2]
__version__='$Revision: 1.75 $'[11:-2]
import sys, string, Globals, Moniker, tempfile, ExtensionClass
from marshal import loads, dumps
......@@ -410,9 +410,9 @@ class CopyContainer(ExtensionClass.Base):
except: parent=None
if getSecurityManager().validate(None, parent, None, object):
return
raise 'Unauthorized', absattr(object.id)
raise Unauthorized, absattr(object.id)
else:
raise 'Unauthorized', mt_permission
raise Unauthorized(permission=mt_permission)
#
# XXX: Ancient cruft, left here in true co-dependent fashion
# to keep from breaking old products which don't put
......@@ -434,9 +434,9 @@ class CopyContainer(ExtensionClass.Base):
except: parent=None
if getSecurityManager().validate(None, parent, None, object):
return
raise 'Unauthorized', absattr(object.id)
raise Unauthorized, absattr(object.id)
else:
raise 'Unauthorized', method_name
raise Unauthorized, method_name
raise CopyError, MessageDialog(
title='Not Supported',
......
......@@ -87,13 +87,14 @@
Folders are the basic container objects and are analogous to directories.
$Id: Folder.py,v 1.95 2001/10/15 14:38:13 evan Exp $"""
$Id: Folder.py,v 1.96 2001/10/19 15:12:26 shane Exp $"""
__version__='$Revision: 1.95 $'[11:-2]
__version__='$Revision: 1.96 $'[11:-2]
import Globals, SimpleItem, ObjectManager, PropertyManager
import AccessControl.Role, webdav.Collection, FindSupport
from webdav.WriteLockInterface import WriteLockInterface
from AccessControl import Unauthorized
from Globals import DTMLFile
from AccessControl import getSecurityManager
......@@ -121,14 +122,14 @@ def manage_addFolder(self, id, title='',
if createUserF:
if not checkPermission('Add User Folders', ob):
raise 'Unauthorized', (
raise Unauthorized, (
'You are not authorized to add User Folders.'
)
ob.manage_addUserFolder()
if createPublic:
if not checkPermission('Add Page Templates', ob):
raise 'Unauthorized', (
raise Unauthorized, (
'You are not authorized to add Page Templates.'
)
ob.manage_addProduct['PageTemplates'].manage_addPageTemplate(
......
......@@ -84,12 +84,13 @@
##############################################################################
'''This module implements a mix-in for traversable objects.
$Id: Traversable.py,v 1.11 2001/09/11 14:31:25 evan Exp $'''
__version__='$Revision: 1.11 $'[11:-2]
$Id: Traversable.py,v 1.12 2001/10/19 15:12:26 shane Exp $'''
__version__='$Revision: 1.12 $'[11:-2]
from Acquisition import Acquired, aq_inner, aq_parent, aq_base
from AccessControl import getSecurityManager
from AccessControl import Unauthorized
from string import split, join
from urllib import quote
......@@ -165,7 +166,7 @@ class Traversable:
pop()
self=self.getPhysicalRoot()
if (restricted and not securityManager.validateValue(self)):
raise 'Unauthorized', name
raise Unauthorized, name
try:
object = self
......@@ -181,7 +182,7 @@ class Traversable:
if o is not M:
if (restricted and not securityManager.validate(
object, object,name, o)):
raise 'Unauthorized', name
raise Unauthorized, name
object=o
continue
......@@ -198,7 +199,7 @@ class Traversable:
container = object
if (not securityManager.validate(object,
container, name, o)):
raise 'Unauthorized', name
raise Unauthorized, name
else:
o=get(object, name, M)
......@@ -209,17 +210,17 @@ class Traversable:
# value wasn't acquired
if not securityManager.validate(
object, object, name, o):
raise 'Unauthorized', name
raise Unauthorized, name
else:
if not securityManager.validate(
object, N, name, o):
raise 'Unauthorized', name
raise Unauthorized, name
else:
o=object[name]
if (restricted and not securityManager.validate(
object, object, N, o)):
raise 'Unauthorized', name
raise Unauthorized, name
object=o
......
......@@ -84,12 +84,13 @@
##############################################################################
'''CGI Response Output formatter
$Id: BaseResponse.py,v 1.8 2001/04/26 14:40:07 andreas Exp $'''
__version__='$Revision: 1.8 $'[11:-2]
$Id: BaseResponse.py,v 1.9 2001/10/19 15:12:27 shane Exp $'''
__version__='$Revision: 1.9 $'[11:-2]
import string, types, sys
from string import find, rfind, lower, upper, strip, split, join, translate
from types import StringType, InstanceType
from zExceptions import Unauthorized
class BaseResponse:
"""Base Response Class
......@@ -226,4 +227,4 @@ class BaseResponse:
Make sure to generate an appropriate challenge, as appropriate.
"""
raise 'Unauthorized'
raise Unauthorized
......@@ -84,13 +84,14 @@
##############################################################################
'''CGI Response Output formatter
$Id: HTTPResponse.py,v 1.48 2001/08/07 18:36:48 evan Exp $'''
__version__='$Revision: 1.48 $'[11:-2]
$Id: HTTPResponse.py,v 1.49 2001/10/19 15:12:27 shane Exp $'''
__version__='$Revision: 1.49 $'[11:-2]
import string, types, sys, re
from string import find, rfind, lower, upper, strip, split, join, translate
from types import StringType, InstanceType, LongType
from BaseResponse import BaseResponse
from zExceptions import Unauthorized
nl2sp=string.maketrans('\n',' ')
......@@ -578,7 +579,7 @@ class HTTPResponse(BaseResponse):
m=m+'<p>\nUsername and password are not correct.'
else:
m=m+'<p>\nNo Authorization header found.'
raise 'Unauthorized', m
raise Unauthorized, m
def exception(self, fatal=0, info=None,
absuri_match=re.compile(r'\w+://[\w\.]+').match,
......@@ -588,7 +589,11 @@ class HTTPResponse(BaseResponse):
if type(info) is type(()) and len(info)==3: t,v,tb = info
else: t,v,tb = sys.exc_info()
if str(t)=='Unauthorized': self._unauthorized()
if t=='Unauthorized' or t == Unauthorized or (
isinstance(t, types.ClassType) and issubclass(t, Unauthorized)
):
t = 'Unauthorized'
self._unauthorized()
stb=tb
......
......@@ -85,7 +85,7 @@
"""WebDAV support - null resource objects."""
__version__='$Revision: 1.32 $'[11:-2]
__version__='$Revision: 1.33 $'[11:-2]
import sys, os, string, mimetypes, Globals, davcmds
import Acquisition, OFS.content_types
......@@ -96,6 +96,7 @@ from Resource import Resource
from Globals import Persistent, DTMLFile
from WriteLockInterface import WriteLockInterface
import OFS.SimpleItem
from zExceptions import Unauthorized
class NullResource(Persistent, Acquisition.Implicit, Resource):
"""Null resources are used to handle HTTP method calls on
......@@ -179,8 +180,8 @@ class NullResource(Persistent, Acquisition.Implicit, Resource):
# check the clipboard.
try:
parent._verifyObjectPaste(ob.__of__(parent), 0)
except 'Unauthorized':
raise 'Unauthorized', sys.exc_info()[1]
except Unauthorized:
raise
except:
raise 'Forbidden', sys.exc_info()[1]
......@@ -429,8 +430,8 @@ class LockNullResource(NullResource, OFS.SimpleItem.Item_w__name__):
# Verify that the user can create this type of object
try:
parent._verifyObjectPaste(ob.__of__(parent), 0)
except 'Unauthorized':
raise 'Unauthorized', sys.exc_info()[1]
except Unauthorized:
raise
except:
raise 'Forbidden', sys.exc_info()[1]
......
......@@ -85,7 +85,7 @@
"""WebDAV support - resource objects."""
__version__='$Revision: 1.47 $'[11:-2]
__version__='$Revision: 1.48 $'[11:-2]
import sys, os, string, mimetypes, davcmds, ExtensionClass, Lockable
from common import absattr, aq_base, urlfix, rfc1123_date, tokenFinder, urlbase
......@@ -95,6 +95,7 @@ from AccessControl import getSecurityManager
from WriteLockInterface import WriteLockInterface
import Globals, time
from ZPublisher.HTTPRangeSupport import HTTPRangeInterface
from zExceptions import Unauthorized
class Resource(ExtensionClass.Base, Lockable.LockableItem):
"""The Resource mixin class provides basic WebDAV support for
......@@ -155,7 +156,7 @@ class Resource(ExtensionClass.Base, Lockable.LockableItem):
method)
except: pass
raise 'Unauthorized', msg
raise Unauthorized, msg
def dav__simpleifhandler(self, request, response, method='PUT',
col=0, url=None, refresh=0):
......@@ -394,8 +395,8 @@ class Resource(ExtensionClass.Base, Lockable.LockableItem):
try: parent._checkId(name, allow_dup=1)
except: raise 'Forbidden', sys.exc_info()[1]
try: parent._verifyObjectPaste(self)
except 'Unauthorized':
raise 'Unauthorized', sys.exc_info()[1]
except Unauthorized:
raise
except: raise 'Forbidden', sys.exc_info()[1]
# Now check locks. The If header on a copy only cares about the
......@@ -483,8 +484,7 @@ class Resource(ExtensionClass.Base, Lockable.LockableItem):
except:
raise 'Forbidden', sys.exc_info()[1]
try: parent._verifyObjectPaste(self)
except 'Unauthorized':
raise 'Unauthorized', sys.exc_info()[1]
except Unauthorized: raise
except: raise 'Forbidden', sys.exc_info()[1]
# Now check locks. Since we're affecting the resource that we're
......
......@@ -82,172 +82,12 @@
# attributions are listed in the accompanying credits file.
#
##############################################################################
__doc__='''Define Zope\'s default security policy
"""General exceptions that wish they were standard exceptions
These exceptions are so general purpose that they don't belong in Zope
application-specific packages.
$Id: pZopeSecurityPolicy.py,v 1.1 2001/08/08 15:57:49 matt Exp $'''
__version__='$Revision: 1.1 $'[11:-2]
$Id: __init__.py,v 1.2 2001/10/19 15:12:28 shane Exp $
"""
from types import StringType
import SimpleObjectPolicies
from AccessControl import Unauthorized
_noroles=SimpleObjectPolicies._noroles
from zLOG import LOG, PROBLEM
from Acquisition import aq_base
from PermissionRole import _what_not_even_god_should_do, rolesForPermissionOn
class ZopeSecurityPolicy:
def validate(self, accessed, container, name, value, context,
roles=_noroles, None=None, type=type, IntType=type(0),
DictType=type({}), getattr=getattr, _noroles=_noroles,
StringType=type(''),
Containers=SimpleObjectPolicies.Containers,
valid_aq_=('aq_parent','aq_explicit')):
############################################################
# Provide special rules for the acquisition attributes
if type(name) is StringType:
if name[:3]=='aq_' and name not in valid_aq_:
return 0
containerbase = aq_base(container)
accessedbase=getattr(accessed, 'aq_base', container)
############################################################
# If roles weren't passed in, we'll try to get them from the object
if roles is _noroles:
roles=getattr(value, '__roles__', _noroles)
############################################################
# We still might not have any roles
if roles is _noroles:
############################################################
# We have an object without roles and we didn't get a list
# of roles passed in. Presumably, the value is some simple
# object like a string or a list. We'll try to get roles
# from its container.
if container is None: return 0 # Bail if no container
roles=getattr(container, '__roles__', _noroles)
if roles is _noroles:
aq=getattr(container, 'aq_acquire', None)
if aq is None:
roles=_noroles
if containerbase is not accessedbase: return 0
else:
# Try to acquire roles
try: roles=aq('__roles__')
except AttributeError:
roles=_noroles
if containerbase is not accessedbase: return 0
# We need to make sure that we are allowed to
# get unprotected attributes from the container. We are
# allowed for certain simple containers and if the
# container says we can. Simple containers
# may also impose name restrictions.
p=Containers(type(container), None)
if p is None:
p=getattr(container,
'__allow_access_to_unprotected_subobjects__', None)
if p is not None:
tp=type(p)
if tp is not IntType:
if tp is DictType:
p=p.get(name, None)
else:
p=p(name, value)
if not p:
if (containerbase is accessedbase):
raise Unauthorized, cleanupName(name, value)
else:
return 0
if roles is _noroles: return 1
# We are going to need a security-aware object to pass
# to allowed(). We'll use the container.
value=container
# Short-circuit tests if we can:
try:
if roles is None or 'Anonymous' in roles: return 1
except TypeError:
# 'roles' isn't a sequence
LOG('Zope Security Policy', PROBLEM, "'%s' passed as roles"
" during validation of '%s' is not a sequence." % (
`roles`, name))
raise
# Check executable security
stack=context.stack
if stack:
eo=stack[-1]
# If the executable had an owner, can it execute?
owner=eo.getOwner()
if (owner is not None) and not owner.allowed(value, roles):
# We don't want someone to acquire if they can't
# get an unacquired!
if accessedbase is containerbase:
raise Unauthorized, (
'You are not authorized to access <em>%s</em>.' \
% cleanupName(name, value))
return 0
# Proxy roles, which are a lot safer now.
proxy_roles=getattr(eo, '_proxy_roles', None)
if proxy_roles:
for r in proxy_roles:
if r in roles: return 1
# Proxy roles actually limit access!
if accessedbase is containerbase:
raise Unauthorized, (
'You are not authorized to access <em>%s</em>.' \
% cleanupName(name, value))
return 0
try:
if context.user.allowed(value, roles): return 1
except AttributeError: pass
# We don't want someone to acquire if they can't get an unacquired!
if accessedbase is containerbase:
raise Unauthorized, (
'You are not authorized to access <em>%s</em>.' \
% cleanupName(name, value))
return 0
def checkPermission(self, permission, object, context):
roles=rolesForPermissionOn(permission, object)
if type(roles) is StringType:
roles=[roles]
return context.user.allowed(object, roles)
def cleanupName(name, value):
# If name is not available, tries to get it from the value.
_name = name
if _name is None and value is not None:
try: _name = value.id
except:
try: _name = value.__name__
except: pass
if callable(_name):
try: _name = _name()
except: pass
return _name
from unauthorized import Unauthorized
......@@ -82,178 +82,57 @@
# attributions are listed in the accompanying credits file.
#
##############################################################################
__doc__='''Objects that implement Permission-based roles.
$Id: pPermissionRole.py,v 1.1 2001/08/08 15:57:49 matt Exp $'''
__version__='$Revision: 1.1 $'[11:-2]
import sys
from ExtensionClass import Base
import string
name_trans=filter(lambda c, an=string.letters+string.digits+'_': c not in an,
map(chr,range(256)))
name_trans=string.maketrans(string.join(name_trans,''), '_'*len(name_trans))
def rolesForPermissionOn(perm, object, default=('Manager',)):
"""Return the roles that have the given permission on the given object
"""
im=imPermissionRole()
im._p='_'+string.translate(perm, name_trans)+"_Permission"
im._d=default
return im.__of__(object)
class PermissionRole(Base):
"""Implement permission-based roles.
Under normal circumstances, our __of__ method will be
called with an unwrapped object. The result will then be called
with a wrapped object, if the original object was wrapped.
To deal with this, we have to create an intermediate object.
"""
def __init__(self, name, default=('Manager',)):
self.__name__=name
self._p='_'+string.translate(name,name_trans)+"_Permission"
self._d=default
def __of__(self, parent, None=None, getattr=getattr):
r=imPermissionRole()
r._p=self._p
r._pa=parent
r._d=self._d
p=getattr(parent, 'aq_inner', None)
if p is not None:
return r.__of__(p)
else:
return r
# This is used when a permission maps explicitly to no permission.
_what_not_even_god_should_do=[]
class imPermissionRole(Base):
"""Implement permission-based roles
"""
def __of__(self, parent,tt=type(()),st=type(''),getattr=getattr,None=None):
obj=parent
n=self._p
r=None
while 1:
if hasattr(obj,n):
roles=getattr(obj, n)
if roles is None: return 'Anonymous',
t=type(roles)
if t is tt:
# If we get a tuple, then we don't acquire
if r is None: return roles
return r+list(roles)
if t is st:
# We found roles set to a name. Start over
# with the new permission name. If the permission
# name is '', then treat as private!
if roles:
if roles != n:
n=roles
# If we find a name that is the same as the
# current name, we just ignore it.
roles=None
else:
return _what_not_even_god_should_do
elif roles:
if r is None: r=list(roles)
else: r=r+list(roles)
obj=getattr(obj, 'aq_inner', None)
if obj is None: break
obj=obj.aq_parent
if r is None: r=self._d
return r
# The following methods are needed in the unlikely case that an unwrapped
# object is accessed:
def __getitem__(self, i):
try:
v=self._v
except:
v=self._v=self.__of__(self._pa)
del self._pa
return v[i]
"""
$Id: unauthorized.py,v 1.2 2001/10/19 15:12:28 shane Exp $
"""
class Unauthorized(Exception):
"""Some user wasn't allowed to access a resource"""
def __init__(self, message=None, value=None, needed=None, name=None, **kw):
"""Possible signatures:
Unauthorized()
Unauthorized(message) # Note that message includes a space
Unauthorized(name)
Unauthorized(name, value)
Unauthorized(name, value, needed)
Unauthorized(message, value, needed, name)
def __len__(self):
try:
v=self._v
except:
v=self._v=self.__of__(self._pa)
del self._pa
return len(v)
##############################################################################
# Test functions:
#
def main():
# The "main" program for this module
import sys
sys.path.append('/projects/_/ExtensionClass')
from Acquisition import Implicit
class I(Implicit):
x__roles__=PermissionRole('x')
y__roles__=PermissionRole('y')
z__roles__=PermissionRole('z')
def x(self): pass
def y(self): pass
def z(self): pass
Where needed is a mapping objects with items represnting requirements
(e.g. {'permission': 'add spam'}). Any extra keyword arguments
provides are added to needed.
"""
if name is None and message is not None and len(message.split()) <= 1:
# First arg is a name, not a message
name=message
message=None
self.name=name
self.message=message
self.value=value
a=I()
a.b=I()
a.b.c=I()
a.q=I()
a.q._x_Permission=('foo',)
a._y_Permission=('bar',)
a._z_Permission=('zee',)
a.b.c._y_Permission=('Manage',)
a.b._z_Permission=['also']
print a.x.__roles__, list(a.x.__roles__)
print a.b.x.__roles__
print a.b.c.x.__roles__
print a.q.x.__roles__
print a.b.q.x.__roles__
print a.b.c.q.x.__roles__
print
print a.y.__roles__, list(a.y.__roles__)
print a.b.y.__roles__
print a.b.c.y.__roles__
print a.q.y.__roles__
print a.b.q.y.__roles__
print a.b.c.q.y.__roles__
print
if kw:
if needed: needed.update(kw)
else: needed=kw
self.needed=needed
def __str__(self):
if self.message is not None: return self.message
if self.name is not None:
return ("You are not allowed to access %s in this context"
% self.name)
elif self.value is not None:
return ("You are not allowed to access %s in this context"
% self.getValueName(self.value))
def getValueName(self):
v=self.value
vname=getattr(v, '__name__', None)
if vname: return vname
c = getattr(v, '__class__', type(v))
c = getattr(c, '__name__', 'object')
return "a particular %s" % c
print a.z.__roles__, list(a.z.__roles__)
print a.b.z.__roles__
print a.b.c.z.__roles__
print a.q.z.__roles__
print a.b.q.z.__roles__
print a.b.c.q.z.__roles__
print
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