[CMF-checkins] SVN: CMF/branches/2.1/ Forward port fixes from 1.6
branch r73950:73969 and r74140:74202 (POST only fixes and fix
for skin lookup
Alec Mitchell
apm13 at columbia.edu
Sat Apr 21 00:54:51 EDT 2007
Log message for revision 74276:
Forward port fixes from 1.6 branch r73950:73969 and r74140:74202 (POST only fixes and fix for skin lookup
Changed:
U CMF/branches/2.1/CHANGES.txt
U CMF/branches/2.1/CMFCore/MembershipTool.py
U CMF/branches/2.1/CMFCore/RegistrationTool.py
U CMF/branches/2.1/CMFCore/SkinsTool.py
U CMF/branches/2.1/CMFCore/WorkflowTool.py
U CMF/branches/2.1/CMFCore/dtml/selectWorkflows.dtml
U CMF/branches/2.1/CMFCore/utils.py
U CMF/branches/2.1/CMFDefault/RegistrationTool.py
U CMF/branches/2.1/CMFDefault/skins/zpt_control/change_password.py
U CMF/branches/2.1/CMFDefault/skins/zpt_control/folder_localrole_edit.py
U CMF/branches/2.1/CMFDefault/skins/zpt_control/members_add_control.py
U CMF/branches/2.1/CMFDefault/skins/zpt_control/members_delete_control.py
U CMF/branches/2.1/DCWorkflow/States.py
U CMF/branches/2.1/DCWorkflow/WorkflowUIMixin.py
-=-
Modified: CMF/branches/2.1/CHANGES.txt
===================================================================
--- CMF/branches/2.1/CHANGES.txt 2007-04-21 04:36:04 UTC (rev 74275)
+++ CMF/branches/2.1/CHANGES.txt 2007-04-21 04:54:50 UTC (rev 74276)
@@ -2,6 +2,13 @@
Bug Fixes
+ - Use the property API to get the member specific skin, because
+ direct attribute access won't work with PAS based membership.
+ (http://dev.plone.org/plone/ticket/5904)
+
+ - Add POST-only protections to security critical methods (see
+ http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2007-0240).
+
- Added forward-compatibility fix for running tests under the
testrunner shipped with Zope 2.11.
Modified: CMF/branches/2.1/CMFCore/MembershipTool.py
===================================================================
--- CMF/branches/2.1/CMFCore/MembershipTool.py 2007-04-21 04:36:04 UTC (rev 74275)
+++ CMF/branches/2.1/CMFCore/MembershipTool.py 2007-04-21 04:54:50 UTC (rev 74276)
@@ -52,6 +52,7 @@
from utils import _dtmldir
from utils import _getAuthenticatedUser
from utils import UniqueObject
+from utils import postonly
logger = logging.getLogger('CMFCore.MembershipTool')
@@ -96,7 +97,7 @@
manage_mapRoles = DTMLFile('membershipRolemapping', _dtmldir )
security.declareProtected(SetOwnPassword, 'setPassword')
- def setPassword(self, password, domains=None):
+ def setPassword(self, password, domains=None, REQUEST=None):
'''Allows the authenticated member to set his/her own password.
'''
registration = queryUtility(IRegistrationTool)
@@ -109,6 +110,7 @@
member.setSecurityProfile(password=password, domains=domains)
else:
raise BadRequest('Not logged in.')
+ setPassword = postonly(setPassword)
security.declarePublic('getAuthenticatedMember')
def getAuthenticatedMember(self):
@@ -173,7 +175,7 @@
return roles
security.declareProtected(ManagePortal, 'setRoleMapping')
- def setRoleMapping(self, portal_role, userfolder_role):
+ def setRoleMapping(self, portal_role, userfolder_role, REQUEST=None):
"""
set the mapping of roles between roles understood by
the portal and roles coming from outside user sources
@@ -189,6 +191,7 @@
title ='Mapping updated',
message='The Role mappings have been updated',
action ='manage_mapRoles')
+ setRoleMapping = postonly(setRoleMapping)
security.declareProtected(ManagePortal, 'getMappedRole')
def getMappedRole(self, portal_role):
@@ -289,7 +292,7 @@
createMemberarea = createMemberArea
security.declareProtected(ManageUsers, 'deleteMemberArea')
- def deleteMemberArea(self, member_id):
+ def deleteMemberArea(self, member_id, REQUEST=None):
""" Delete member area of member specified by member_id.
"""
members = self.getMembersFolder()
@@ -300,6 +303,7 @@
return 1
else:
return 0
+ deleteMemberArea = postonly(deleteMemberArea)
security.declarePublic('isAnonymousUser')
def isAnonymousUser(self):
@@ -429,7 +433,8 @@
return tuple(local_roles)
security.declareProtected(View, 'setLocalRoles')
- def setLocalRoles(self, obj, member_ids, member_role, reindex=1):
+ def setLocalRoles(self, obj, member_ids, member_role, reindex=1,
+ REQUEST=None):
""" Add local roles on an item.
"""
if ( _checkPermission(ChangeLocalRoles, obj)
@@ -446,9 +451,11 @@
# reindexObjectSecurity, which is in CMFCatalogAware and
# thus PortalContent and PortalFolder.
obj.reindexObjectSecurity()
+ setLocalRoles = postonly(setLocalRoles)
security.declareProtected(View, 'deleteLocalRoles')
- def deleteLocalRoles(self, obj, member_ids, reindex=1, recursive=0):
+ def deleteLocalRoles(self, obj, member_ids, reindex=1, recursive=0,
+ REQUEST=None):
""" Delete local roles of specified members.
"""
if _checkPermission(ChangeLocalRoles, obj):
@@ -464,6 +471,7 @@
if reindex:
# reindexObjectSecurity is always recursive
obj.reindexObjectSecurity()
+ deleteLocalRoles = postonly(deleteLocalRoles)
security.declarePrivate('addMember')
def addMember(self, id, password, roles, domains, properties=None):
@@ -487,7 +495,7 @@
security.declareProtected(ManageUsers, 'deleteMembers')
def deleteMembers(self, member_ids, delete_memberareas=1,
- delete_localroles=1):
+ delete_localroles=1, REQUEST=None):
""" Delete members specified by member_ids.
"""
@@ -526,6 +534,7 @@
reindex=1, recursive=1 )
return tuple(member_ids)
+ deleteMembers = postonly(deleteMembers)
security.declarePublic('getHomeFolder')
def getHomeFolder(self, id=None, verifyPermission=0):
Modified: CMF/branches/2.1/CMFCore/RegistrationTool.py
===================================================================
--- CMF/branches/2.1/CMFCore/RegistrationTool.py 2007-04-21 04:36:04 UTC (rev 74275)
+++ CMF/branches/2.1/CMFCore/RegistrationTool.py 2007-04-21 04:54:50 UTC (rev 74276)
@@ -39,6 +39,7 @@
from utils import _limitGrantedRoles
from utils import Message as _
from utils import UniqueObject
+from utils import postonly
class RegistrationTool(UniqueObject, SimpleItem, ActionProviderBase):
@@ -133,7 +134,7 @@
security.declareProtected(AddPortalMember, 'addMember')
def addMember(self, id, password, roles=('Member',), domains='',
- properties=None):
+ properties=None, REQUEST=None):
'''Creates a PortalMember and returns it. The properties argument
can be a mapping with additional member properties. Raises an
exception if the given id already exists, the password does not
@@ -165,6 +166,7 @@
member = membership.getMemberById(id)
self.afterAdd(member, id, password, properties)
return member
+ addMember = postonly(addMember)
security.declareProtected(AddPortalMember, 'isMemberIdAllowed')
def isMemberIdAllowed(self, id):
Modified: CMF/branches/2.1/CMFCore/SkinsTool.py
===================================================================
--- CMF/branches/2.1/CMFCore/SkinsTool.py 2007-04-21 04:36:04 UTC (rev 74275)
+++ CMF/branches/2.1/CMFCore/SkinsTool.py 2007-04-21 04:54:50 UTC (rev 74276)
@@ -312,8 +312,8 @@
mtool = getUtility(IMembershipTool)
utool = getUtility(IURLTool)
member = mtool.getAuthenticatedMember()
- if hasattr(aq_base(member), 'portal_skin'):
- mskin = member.portal_skin
+ if hasattr(aq_base(member), 'getProperty'):
+ mskin = member.getProperty('portal_skin', None)
if mskin:
req = self.REQUEST
cookie = req.cookies.get(self.request_varname, None)
Modified: CMF/branches/2.1/CMFCore/WorkflowTool.py
===================================================================
--- CMF/branches/2.1/CMFCore/WorkflowTool.py 2007-04-21 04:36:04 UTC (rev 74275)
+++ CMF/branches/2.1/CMFCore/WorkflowTool.py 2007-04-21 04:54:50 UTC (rev 74276)
@@ -41,6 +41,7 @@
from utils import Message as _
from utils import registerToolInterface
from utils import UniqueObject
+from utils import postonly
from WorkflowCore import ObjectDeleted
from WorkflowCore import ObjectMoved
from WorkflowCore import WorkflowException
@@ -155,6 +156,7 @@
if REQUEST is not None:
return self.manage_selectWorkflows(REQUEST,
manage_tabs_message='Changed.')
+ manage_changeWorkflows = postonly(manage_changeWorkflows)
#
# 'IActionProvider' interface methods
@@ -362,7 +364,7 @@
# 'IConfigurableWorkflowTool' interface methods
#
security.declareProtected(ManagePortal, 'setDefaultChain')
- def setDefaultChain(self, default_chain):
+ def setDefaultChain(self, default_chain, REQUEST=None):
""" Set the default chain for this tool.
"""
default_chain = default_chain.replace(',', ' ')
@@ -374,9 +376,11 @@
ids.append(wf_id)
self._default_chain = tuple(ids)
+ setDefaultChain = postonly(setDefaultChain)
security.declareProtected(ManagePortal, 'setChainForPortalTypes')
- def setChainForPortalTypes(self, pt_names, chain, verify=True):
+ def setChainForPortalTypes(self, pt_names, chain, verify=True,
+ REQUEST=None):
""" Set a chain for specific portal types.
"""
cbt = self._chains_by_type
@@ -398,6 +402,7 @@
if verify and not (type_id in ti_ids):
continue
cbt[type_id] = tuple(chain)
+ setChainForPortalTypes = postonly(setChainForPortalTypes)
security.declarePrivate('getDefaultChain')
def getDefaultChain(self):
@@ -455,6 +460,7 @@
'%d object(s) updated.' % count)
else:
return count
+ updateRoleMappings = postonly(updateRoleMappings)
security.declarePrivate('getWorkflowById')
def getWorkflowById(self, wf_id):
Modified: CMF/branches/2.1/CMFCore/dtml/selectWorkflows.dtml
===================================================================
--- CMF/branches/2.1/CMFCore/dtml/selectWorkflows.dtml 2007-04-21 04:36:04 UTC (rev 74275)
+++ CMF/branches/2.1/CMFCore/dtml/selectWorkflows.dtml 2007-04-21 04:54:50 UTC (rev 74276)
@@ -50,7 +50,7 @@
Click the button below to update the security settings of all
workflow-aware objects in this portal.
-<form action="updateRoleMappings" method="GET">
+<form action="updateRoleMappings" method="POST">
<input type="submit" name="submit" value="Update security settings" />
</form>
</p>
Modified: CMF/branches/2.1/CMFCore/utils.py
===================================================================
--- CMF/branches/2.1/CMFCore/utils.py 2007-04-21 04:36:04 UTC (rev 74275)
+++ CMF/branches/2.1/CMFCore/utils.py 2007-04-21 04:54:50 UTC (rev 74276)
@@ -929,3 +929,14 @@
security.declarePublic('Message')
Message = MessageFactory('cmf_default')
+
+# postonly decorator is only available in Zope 2.8.9, 2.9.7, 2.10.3 and 2.11,
+# or in Hotfix_20070320.
+try:
+ from AccessControl.requestmethod import postonly
+except ImportError:
+ try:
+ from Products.Hotfix_20070320 import postonly
+ except ImportError:
+ def postonly(callable):
+ return callable
Modified: CMF/branches/2.1/CMFDefault/RegistrationTool.py
===================================================================
--- CMF/branches/2.1/CMFDefault/RegistrationTool.py 2007-04-21 04:36:04 UTC (rev 74275)
+++ CMF/branches/2.1/CMFDefault/RegistrationTool.py 2007-04-21 04:54:50 UTC (rev 74276)
@@ -28,6 +28,7 @@
from Products.CMFCore.RegistrationTool import RegistrationTool as BaseTool
from Products.CMFCore.utils import _checkPermission
from Products.CMFCore.utils import registerToolInterface
+from Products.CMFCore.utils import postonly
from permissions import ManagePortal
from utils import checkEmailAddress
@@ -194,6 +195,7 @@
, password=None
, roles=None
, domains=None
+ , REQUEST = None
):
""" Edit a user's properties and security settings
@@ -207,6 +209,7 @@
member.setSecurityProfile(password,roles,domains)
return member
+ editMember = postonly(editMember)
InitializeClass(RegistrationTool)
registerToolInterface('portal_registration', IRegistrationTool)
Modified: CMF/branches/2.1/CMFDefault/skins/zpt_control/change_password.py
===================================================================
--- CMF/branches/2.1/CMFDefault/skins/zpt_control/change_password.py 2007-04-21 04:36:04 UTC (rev 74275)
+++ CMF/branches/2.1/CMFDefault/skins/zpt_control/change_password.py 2007-04-21 04:54:50 UTC (rev 74276)
@@ -12,7 +12,7 @@
return context.setStatus(False, result)
member = mtool.getAuthenticatedMember()
-mtool.setPassword(password, domains)
+mtool.setPassword(password, domains, REQUEST=context.REQUEST)
if member.getProperty('last_login_time') == DateTime('1999/01/01'):
member.setProperties(last_login_time='2000/01/01')
Modified: CMF/branches/2.1/CMFDefault/skins/zpt_control/folder_localrole_edit.py
===================================================================
--- CMF/branches/2.1/CMFDefault/skins/zpt_control/folder_localrole_edit.py 2007-04-21 04:36:04 UTC (rev 74275)
+++ CMF/branches/2.1/CMFDefault/skins/zpt_control/folder_localrole_edit.py 2007-04-21 04:54:50 UTC (rev 74276)
@@ -9,10 +9,12 @@
if change_type == 'add':
mtool.setLocalRoles(obj=context,
member_ids=context.REQUEST.get('member_ids', ()),
- member_role=context.REQUEST.get('member_role', ''))
+ member_role=context.REQUEST.get('member_role', ''),
+ REQUEST=context.REQUEST)
else:
mtool.deleteLocalRoles(obj=context,
- member_ids=context.REQUEST.get('member_ids', ()))
+ member_ids=context.REQUEST.get('member_ids', ()),
+ REQUEST=context.REQUEST)
context.setStatus(True, _(u'Local Roles changed.'))
context.setRedirect(context, 'object/localroles')
Modified: CMF/branches/2.1/CMFDefault/skins/zpt_control/members_add_control.py
===================================================================
--- CMF/branches/2.1/CMFDefault/skins/zpt_control/members_add_control.py 2007-04-21 04:36:04 UTC (rev 74275)
+++ CMF/branches/2.1/CMFDefault/skins/zpt_control/members_add_control.py 2007-04-21 04:54:50 UTC (rev 74276)
@@ -12,7 +12,8 @@
try:
rtool.addMember( id=member_id, password=password,
properties={'username': member_id,
- 'email': member_email} )
+ 'email': member_email},
+ REQUEST=context.REQUEST)
except ValueError, errmsg:
return context.setStatus(False, errmsg)
else:
Modified: CMF/branches/2.1/CMFDefault/skins/zpt_control/members_delete_control.py
===================================================================
--- CMF/branches/2.1/CMFDefault/skins/zpt_control/members_delete_control.py 2007-04-21 04:36:04 UTC (rev 74275)
+++ CMF/branches/2.1/CMFDefault/skins/zpt_control/members_delete_control.py 2007-04-21 04:54:50 UTC (rev 74276)
@@ -6,7 +6,7 @@
mtool = getToolByInterfaceName('Products.CMFCore.interfaces.IMembershipTool')
-mtool.deleteMembers(ids)
+mtool.deleteMembers(ids, REQUEST=context.REQUEST)
if len(ids) == 1:
return context.setStatus(True, _(u'Selected member deleted.'))
Modified: CMF/branches/2.1/DCWorkflow/States.py
===================================================================
--- CMF/branches/2.1/DCWorkflow/States.py 2007-04-21 04:36:04 UTC (rev 74275)
+++ CMF/branches/2.1/DCWorkflow/States.py 2007-04-21 04:54:50 UTC (rev 74276)
@@ -27,6 +27,7 @@
from ContainerTab import ContainerTab
from permissions import ManagePortal
from utils import _dtmldir
+from Products.CMFCore.utils import postonly
class StateDefinition(SimpleItem):
@@ -213,8 +214,9 @@
roles = tuple(roles)
pr[p] = roles
return self.manage_permissions(REQUEST, 'Permissions changed.')
+ setPermissions = postonly(setPermissions)
- def setPermission(self, permission, acquired, roles):
+ def setPermission(self, permission, acquired, roles, REQUEST=None):
"""Set a permission for this State."""
pr = self.permission_roles
if pr is None:
@@ -224,6 +226,7 @@
else:
roles = tuple(roles)
pr[permission] = roles
+ setPermission = postonly(setPermission)
manage_groups = PageTemplateFile('state_groups.pt', _dtmldir)
@@ -247,6 +250,7 @@
RESPONSE.redirect(
"%s/manage_groups?manage_tabs_message=Groups+changed."
% self.absolute_url())
+ setGroups = postonly(setGroups)
InitializeClass(StateDefinition)
Modified: CMF/branches/2.1/DCWorkflow/WorkflowUIMixin.py
===================================================================
--- CMF/branches/2.1/DCWorkflow/WorkflowUIMixin.py 2007-04-21 04:36:04 UTC (rev 74275)
+++ CMF/branches/2.1/DCWorkflow/WorkflowUIMixin.py 2007-04-21 04:54:50 UTC (rev 74276)
@@ -27,6 +27,7 @@
from permissions import ManagePortal
from Guard import Guard
from utils import _dtmldir
+from Products.CMFCore.utils import postonly
try:
#
@@ -66,6 +67,7 @@
if REQUEST is not None:
return self.manage_properties(
REQUEST, manage_tabs_message='Properties changed.')
+ setProperties = postonly(setProperties)
_permissions_form = DTMLFile('workflow_permissions', _dtmldir)
@@ -90,6 +92,7 @@
if REQUEST is not None:
return self.manage_permissions(
REQUEST, manage_tabs_message='Permission added.')
+ addManagedPermission = postonly(addManagedPermission)
security.declareProtected(ManagePortal, 'delManagedPermissions')
def delManagedPermissions(self, ps, REQUEST=None):
@@ -103,6 +106,7 @@
if REQUEST is not None:
return self.manage_permissions(
REQUEST, manage_tabs_message='Permission(s) removed.')
+ delManagedPermissions = postonly(delManagedPermissions)
security.declareProtected(ManagePortal, 'getPossiblePermissions')
def getPossiblePermissions(self):
@@ -132,7 +136,7 @@
return [g['id'] for g in groups]
security.declareProtected(ManagePortal, 'addGroup')
- def addGroup(self, group, RESPONSE=None):
+ def addGroup(self, group, RESPONSE=None, REQUEST=None):
"""Adds a group by name.
"""
if group not in self.getAvailableGroups():
@@ -142,9 +146,10 @@
RESPONSE.redirect(
"%s/manage_groups?manage_tabs_message=Added+group."
% self.absolute_url())
+ addGroup = postonly(addGroup)
security.declareProtected(ManagePortal, 'delGroups')
- def delGroups(self, groups, RESPONSE=None):
+ def delGroups(self, groups, RESPONSE=None, REQUEST=None):
"""Removes groups by name.
"""
self.groups = tuple([g for g in self.groups if g not in groups])
@@ -152,6 +157,7 @@
RESPONSE.redirect(
"%s/manage_groups?manage_tabs_message=Groups+removed."
% self.absolute_url())
+ delGroups = postonly(delGroups)
security.declareProtected(ManagePortal, 'getAvailableRoles')
def getAvailableRoles(self):
@@ -179,7 +185,7 @@
return self.valid_roles()
security.declareProtected(ManagePortal, 'setRoles')
- def setRoles(self, roles, RESPONSE=None):
+ def setRoles(self, roles, RESPONSE=None, REQUEST=None):
"""Changes the list of roles mapped to groups by this workflow.
"""
avail = self.getAvailableRoles()
@@ -191,6 +197,7 @@
RESPONSE.redirect(
"%s/manage_groups?manage_tabs_message=Roles+changed."
% self.absolute_url())
+ setRoles = postonly(setRoles)
security.declareProtected(ManagePortal, 'getGuard')
def getGuard(self):
More information about the CMF-checkins
mailing list