r716 - in zope2.7/trunk/lib/python: AccessControl App OFS
Products/PythonScripts
Jérémy Bobbio
lunar at alioth.debian.org
Wed Mar 28 17:26:50 UTC 2007
Author: lunar
Date: 2007-03-28 16:26:49 +0000 (Wed, 28 Mar 2007)
New Revision: 716
Added:
zope2.7/trunk/lib/python/AccessControl/requestmethod.py
Modified:
zope2.7/trunk/lib/python/AccessControl/Owned.py
zope2.7/trunk/lib/python/AccessControl/PermissionMapping.py
zope2.7/trunk/lib/python/AccessControl/Role.py
zope2.7/trunk/lib/python/AccessControl/User.py
zope2.7/trunk/lib/python/App/ApplicationManager.py
zope2.7/trunk/lib/python/OFS/DTMLMethod.py
zope2.7/trunk/lib/python/Products/PythonScripts/PythonScript.py
Log:
Backport fix for CVE-2007-0240 from differences between Zope 2.8.8 and 2.8.9.
Modified: zope2.7/trunk/lib/python/AccessControl/Owned.py
===================================================================
--- zope2.7/trunk/lib/python/AccessControl/Owned.py 2007-03-21 14:43:10 UTC (rev 715)
+++ zope2.7/trunk/lib/python/AccessControl/Owned.py 2007-03-28 16:26:49 UTC (rev 716)
@@ -18,6 +18,7 @@
import Globals, urlparse, SpecialUsers, ExtensionClass
from AccessControl import getSecurityManager, Unauthorized
from Acquisition import aq_get, aq_parent, aq_base
+from requestmethod import postonly
UnownableOwner=[]
def ownableFilter(self):
@@ -184,6 +185,7 @@
self.changeOwnership(security.getUser(), recursive)
RESPONSE.redirect(REQUEST['HTTP_REFERER'])
+ manage_takeOwnership = postonly(manage_takeOwnership)
def manage_changeOwnershipType(self, explicit=1,
RESPONSE=None, REQUEST=None):
@@ -204,6 +206,7 @@
del self._owner
if RESPONSE is not None: RESPONSE.redirect(REQUEST['HTTP_REFERER'])
+ manage_changeOwnershipType = postonly(manage_changeOwnershipType)
def _deleteOwnershipAfterAdd(self):
Modified: zope2.7/trunk/lib/python/AccessControl/PermissionMapping.py
===================================================================
--- zope2.7/trunk/lib/python/AccessControl/PermissionMapping.py 2007-03-21 14:43:10 UTC (rev 715)
+++ zope2.7/trunk/lib/python/AccessControl/PermissionMapping.py 2007-03-28 16:26:49 UTC (rev 716)
@@ -22,6 +22,7 @@
from Owned import UnownableOwner
from Globals import InitializeClass
from cgi import escape
+from requestmethod import postonly
class RoleManager:
def manage_getPermissionMapping(self):
@@ -76,6 +77,7 @@
return self.manage_access(
REQUEST,
manage_tabs_message='The permission mapping has been updated')
+ manage_setPermissionMapping = postonly(manage_setPermissionMapping)
def _isBeingUsedAsAMethod(self, REQUEST =None, wannaBe=0):
try:
Modified: zope2.7/trunk/lib/python/AccessControl/Role.py
===================================================================
--- zope2.7/trunk/lib/python/AccessControl/Role.py 2007-03-21 14:43:10 UTC (rev 715)
+++ zope2.7/trunk/lib/python/AccessControl/Role.py 2007-03-28 16:26:49 UTC (rev 716)
@@ -21,6 +21,7 @@
from Permission import Permission
from App.Common import aq_base
from cgi import escape
+from requestmethod import postonly
ListType=type([])
@@ -137,6 +138,7 @@
p.setRole(role_to_manage, name in permissions)
if REQUEST is not None: return self.manage_access(REQUEST)
+ manage_role = postonly(manage_role)
manage_acquiredForm=DTMLFile('dtml/acquiredEdit', globals(),
management_view='Security',
@@ -155,6 +157,7 @@
else: p.setRoles(tuple(roles))
if REQUEST is not None: return self.manage_access(REQUEST)
+ manage_acquiredPermissions = postonly(manage_acquiredPermissions)
manage_permissionForm=DTMLFile('dtml/permissionEdit', globals(),
management_view='Security',
@@ -182,6 +185,7 @@
raise ValueError, (
"The permission <em>%s</em> is invalid." %
escape(permission_to_manage))
+ manage_permission = postonly(manage_permission)
_normal_manage_access=DTMLFile('dtml/access', globals())
@@ -224,6 +228,7 @@
title ='Success!',
message='Your changes have been saved',
action ='manage_access')
+ manage_changePermissions = postonly(manage_changePermissions)
def permissionsOfRole(self, role):
@@ -353,6 +358,7 @@
if REQUEST is not None:
stat='Your changes have been saved.'
return self.manage_listLocalRoles(self, REQUEST, stat=stat)
+ manage_addLocalRoles = postonly(manage_addLocalRoles)
def manage_setLocalRoles(self, userid, roles, REQUEST=None):
"""Set local roles for a user."""
@@ -364,6 +370,7 @@
if REQUEST is not None:
stat='Your changes have been saved.'
return self.manage_listLocalRoles(self, REQUEST, stat=stat)
+ manage_setLocalRoles = postonly(manage_setLocalRoles)
def manage_delLocalRoles(self, userids, REQUEST=None):
"""Remove all local roles for a user."""
@@ -375,6 +382,7 @@
if REQUEST is not None:
stat='Your changes have been saved.'
return self.manage_listLocalRoles(self, REQUEST, stat=stat)
+ manage_delLocalRoles = postonly(manage_delLocalRoles)
@@ -468,6 +476,7 @@
self.__ac_roles__=tuple(data)
if REQUEST is not None:
return self.manage_access(REQUEST)
+ _addRole = postonly(_addRole)
def _delRoles(self, roles, REQUEST=None):
@@ -483,6 +492,7 @@
self.__ac_roles__=tuple(data)
if REQUEST is not None:
return self.manage_access(REQUEST)
+ _delRoles = postonly(_delRoles)
def _has_user_defined_role(self, role):
Modified: zope2.7/trunk/lib/python/AccessControl/User.py
===================================================================
--- zope2.7/trunk/lib/python/AccessControl/User.py 2007-03-21 14:43:10 UTC (rev 715)
+++ zope2.7/trunk/lib/python/AccessControl/User.py 2007-03-28 16:26:49 UTC (rev 716)
@@ -22,6 +22,7 @@
from OFS.SimpleItem import Item
from base64 import decodestring
from App.ImageFile import ImageFile
+from requestmethod import postonly
from Role import RoleManager, DEFAULTMAXLISTUSERS
from PermissionRole import _what_not_even_god_should_do, rolesForPermissionOn
import AuthEncoding
@@ -527,28 +528,33 @@
# Authors of custom user folders don't need to do anything special to
# support these - they will just call the appropriate '_' methods that
# user folder subclasses already implement.
- def userFolderAddUser(self, name, password, roles, domains, **kw):
+ def userFolderAddUser(self, name, password, roles, domains,
+ REQUEST=None, **kw):
"""API method for creating a new user object. Note that not all
user folder implementations support dynamic creation of user
objects."""
if hasattr(self, '_doAddUser'):
return self._doAddUser(name, password, roles, domains, **kw)
raise NotImplementedError
+ userFolderAddUser = postonly(userFolderAddUser)
- def userFolderEditUser(self, name, password, roles, domains, **kw):
+ def userFolderEditUser(self, name, password, roles, domains,
+ REQUEST=None, **kw):
"""API method for changing user object attributes. Note that not
all user folder implementations support changing of user object
attributes."""
if hasattr(self, '_doChangeUser'):
return self._doChangeUser(name, password, roles, domains, **kw)
raise NotImplementedError
+ userFolderEditUser = postonly(userFolderEditUser)
- def userFolderDelUsers(self, names):
+ def userFolderDelUsers(self, names, REQUEST=None):
"""API method for deleting one or more user objects. Note that not
all user folder implementations support deletion of user objects."""
if hasattr(self, '_doDelUsers'):
return self._doDelUsers(names)
raise NotImplementedError
+ userFolderDelUsers = postonly(userFolderDelUsers)
# -----------------------------------
@@ -819,6 +825,7 @@
if REQUEST is not None:
return self.manage_userFolderProperties(
REQUEST, manage_tabs_message='Saved changes.')
+ manage_setUserFolderProperties = postonly(manage_setUserFolderProperties)
def _isPasswordEncrypted(self, pw):
return AuthEncoding.is_encrypted(pw)
@@ -874,6 +881,7 @@
action ='manage_main')
self._doAddUser(name, password, roles, domains)
if REQUEST: return self._mainUser(self, REQUEST)
+ _addUser = postonly(_addUser)
def _changeUser(self,name,password,confirm,roles,domains,REQUEST=None):
@@ -912,6 +920,7 @@
action ='manage_main')
self._doChangeUser(name, password, roles, domains)
if REQUEST: return self._mainUser(self, REQUEST)
+ _changeUser = postonly(_changeUser)
def _delUsers(self,names,REQUEST=None):
if not names:
@@ -921,6 +930,7 @@
action ='manage_main')
self._doDelUsers(names)
if REQUEST: return self._mainUser(self, REQUEST)
+ _delUsers = postonly(_delUsers)
def manage_users(self,submit=None,REQUEST=None,RESPONSE=None):
"""This method handles operations on users for the web based forms
Added: zope2.7/trunk/lib/python/AccessControl/requestmethod.py
===================================================================
--- zope2.7/trunk/lib/python/AccessControl/requestmethod.py 2007-03-21 14:43:10 UTC (rev 715)
+++ zope2.7/trunk/lib/python/AccessControl/requestmethod.py 2007-03-28 16:26:49 UTC (rev 716)
@@ -0,0 +1,71 @@
+#############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors. All Rights Reserved.
+#
+# 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 inspect
+from zExceptions import Forbidden
+from ZPublisher.HTTPRequest import HTTPRequest
+
+def _buildFacade(spec, docstring):
+ """Build a facade function, matching the decorated method in signature.
+
+ Note that defaults are replaced by None, and _curried will reconstruct
+ these to preserve mutable defaults.
+
+ """
+ args = inspect.formatargspec(formatvalue=lambda v: '=None', *spec)
+ callargs = inspect.formatargspec(formatvalue=lambda v: '', *spec)
+ return 'def _facade%s:\n """%s"""\n return _curried%s' % (
+ args, docstring, callargs)
+
+def postonly(callable):
+ """Only allow callable when request method is POST."""
+ spec = inspect.getargspec(callable)
+ args, defaults = spec[0], spec[3]
+ try:
+ r_index = args.index('REQUEST')
+ except ValueError:
+ raise ValueError('No REQUEST parameter in callable signature')
+
+ arglen = len(args)
+ if defaults is not None:
+ defaults = zip(args[arglen - len(defaults):], defaults)
+ arglen -= len(defaults)
+
+ def _curried(*args, **kw):
+ request = None
+
+ if len(args) > r_index:
+ request = args[r_index]
+
+ if isinstance(request, HTTPRequest):
+ if request.get('REQUEST_METHOD', 'GET').upper() != 'POST':
+ raise Forbidden('Request must be POST')
+
+ # Reconstruct keyword arguments
+ if defaults is not None:
+ args, kwparams = args[:arglen], args[arglen:]
+ for positional, (key, default) in zip(kwparams, defaults):
+ if positional is None:
+ kw[key] = default
+ else:
+ kw[key] = positional
+
+ return callable(*args, **kw)
+
+
+ # Build a facade, with a reference to our locally-scoped _curried
+ facade_globs = dict(_curried=_curried)
+ exec _buildFacade(spec, callable.__doc__) in facade_globs
+ return facade_globs['_facade']
+
+__all__ = ('postonly',)
Modified: zope2.7/trunk/lib/python/App/ApplicationManager.py
===================================================================
--- zope2.7/trunk/lib/python/App/ApplicationManager.py 2007-03-21 14:43:10 UTC (rev 715)
+++ zope2.7/trunk/lib/python/App/ApplicationManager.py 2007-03-28 16:26:49 UTC (rev 716)
@@ -33,6 +33,7 @@
from cgi import escape
import zLOG
import Lifetime
+from AccessControl.requestmethod import postonly
try: import thread
except: get_ident=lambda: 0
@@ -402,8 +403,9 @@
</head>
<body>Zope is restarting</body></html>
""" % escape(URL1, 1)
+ manage_restart = postonly(manage_restart)
- def manage_shutdown(self):
+ def manage_shutdown(self, REQUEST=None):
"""Shut down the application"""
try:
user = '"%s"' % getSecurityManager().getUser().getUserName()
@@ -418,6 +420,7 @@
</head>
<body>Zope is shutting down</body></html>
"""
+ manage_shutdown = postonly(manage_shutdown)
def manage_pack(self, days=0, REQUEST=None):
"""Pack the database"""
@@ -430,6 +433,7 @@
REQUEST['RESPONSE'].redirect(
REQUEST['URL1']+'/manage_workspace')
return t
+ manage_pack = postonly(manage_pack)
def revert_points(self): return ()
@@ -480,6 +484,7 @@
db.commitVersion(v)
if REQUEST is not None:
REQUEST['RESPONSE'].redirect(REQUEST['URL1']+'/manage_main')
+ manage_saveVersions = postonly(manage_saveVersions)
def manage_discardVersions(self, versions, REQUEST=None):
"Discard some versions"
@@ -488,6 +493,7 @@
db.abortVersion(v)
if REQUEST is not None:
REQUEST['RESPONSE'].redirect(REQUEST['URL1']+'/manage_main')
+ manage_discardVersions = postonly(manage_discardVersions)
def getSOFTWARE_HOME(self):
return getConfiguration().softwarehome
Modified: zope2.7/trunk/lib/python/OFS/DTMLMethod.py
===================================================================
--- zope2.7/trunk/lib/python/OFS/DTMLMethod.py 2007-03-21 14:43:10 UTC (rev 715)
+++ zope2.7/trunk/lib/python/OFS/DTMLMethod.py 2007-03-28 16:26:49 UTC (rev 716)
@@ -29,6 +29,7 @@
import Globals, sys, Acquisition
from AccessControl import getSecurityManager
from AccessControl.DTML import RestrictedDTML
+from AccessControl.requestmethod import postonly
from Cache import Cacheable
from zExceptions import Forbidden
from zExceptions.TracebackSupplement import PathTracebackSupplement
@@ -324,6 +325,7 @@
if REQUEST:
message="Saved changes."
return self.manage_proxyForm(self,REQUEST,manage_tabs_message=message)
+ manage_proxy = postonly(manage_proxy)
def PrincipiaSearchSource(self):
"Support for searching - the document's contents are searched."
Modified: zope2.7/trunk/lib/python/Products/PythonScripts/PythonScript.py
===================================================================
--- zope2.7/trunk/lib/python/Products/PythonScripts/PythonScript.py 2007-03-21 14:43:10 UTC (rev 715)
+++ zope2.7/trunk/lib/python/Products/PythonScripts/PythonScript.py 2007-03-28 16:26:49 UTC (rev 716)
@@ -33,6 +33,7 @@
from OFS.History import Historical, html_diff
from OFS.Cache import Cacheable
from AccessControl.ZopeGuards import get_safe_globals, guarded_getattr
+from AccessControl.requestmethod import postonly
from zLOG import LOG, ERROR, INFO, PROBLEM
from zExceptions import Forbidden
import Globals
@@ -359,6 +360,7 @@
title ='Success!',
message='Your changes have been saved',
action ='manage_main')
+ manage_proxy = postonly(manage_proxy)
security.declareProtected('Change Python Scripts',
'PUT', 'manage_FTPput', 'write',
More information about the pkg-zope-commits
mailing list