Skip to content

Commit

Permalink
patch pluggable auth csrf with marmoset
Browse files Browse the repository at this point in the history
  • Loading branch information
vangheem committed Sep 26, 2015
1 parent a6cf474 commit 3ffaf6b
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 17 deletions.
5 changes: 5 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ Changelog
3.0.9 (unreleased)
------------------

- patch pluggable auth with marmoset patch because
the patch would not apply otherwise depending on
somewhat-random import order
[vangheem]

- get auto-csrf protection working on the zope root
[vangheem]

Expand Down
11 changes: 11 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -195,3 +195,14 @@ To disable all automatic CSRF protection, set the environment variable

WARNING! It is very dangerous to do this. Do not do this unless the zeo client
with this setting is not public and you know what you are doing.


Notes
=====

This package monkey patches a number of modules in order to better handle CSRF
protection::

- Archetypes add forms, add csrf
- Zope2 object locking support
- pluggable auth csrf protection
18 changes: 1 addition & 17 deletions plone/protect/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -59,20 +59,4 @@
replacement=".monkey.wl_lockmapping"
preserveOriginal="True"
/>

<monkey:patch
zcml:condition="installed Products.PluggableAuthService.utils.getCSRFToken"
description="Patch old pluggable auth to use plone mechanism"
class="Products.PluggableAuthService.utils"
original="getCSRFToken"
replacement=".monkey.pluggableauth__getCSRFToken"
/>
<monkey:patch
zcml:condition="installed Products.PluggableAuthService.utils.checkCSRFToken"
description="Patch old pluggable auth to use plone mechanism"
class="Products.PluggableAuthService.utils"
original="checkCSRFToken"
replacement=".monkey.pluggableauth__checkCSRFToken"
/>

</configure>
</configure>
15 changes: 15 additions & 0 deletions plone/protect/monkey.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from urlparse import urlparse, urljoin
from plone.protect.auto import safeWrite
import inspect
from Products.PluggableAuthService import utils as pluggable_utils


def RedirectTo__call__(self, controller_state):
Expand Down Expand Up @@ -51,3 +53,16 @@ def pluggableauth__checkCSRFToken(request, token='csrf_token', raises=True):
let plone.protect do it's job
"""
pass


def marmoset_patch(func, replacement):
source = inspect.getsource(replacement)
exec source in func.func_globals
func.func_code = replacement.func_code


# otherwise the patches do not get applied in some cases
if hasattr(pluggable_utils, 'checkCSRFToken'):
marmoset_patch(pluggable_utils.checkCSRFToken, pluggableauth__checkCSRFToken)
if hasattr(pluggable_utils, 'getCSRFToken'):
marmoset_patch(pluggable_utils.getCSRFToken, pluggableauth__getCSRFToken)
27 changes: 27 additions & 0 deletions plone/protect/tests/testPatches.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from plone.app.testing import SITE_OWNER_NAME
from plone.app.testing import SITE_OWNER_PASSWORD
from plone.protect.testing import PROTECT_FUNCTIONAL_TESTING
from plone.testing.z2 import Browser
import unittest2 as unittest


class TestCSRF(unittest.TestCase):
layer = PROTECT_FUNCTIONAL_TESTING

def setUp(self):
self.portal = self.layer['portal']
self.browser = Browser(self.layer['app'])
self.request = self.layer['request']
self.browser.addHeader(
'Authorization', 'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD,))

def test_change_password_on_root_does_not_throw_other_csrf_protection(self):
self.browser.open('%s/acl_users/users/manage_users?user_id=%s&passwd=1' % (
self.layer['app'].absolute_url(), SITE_OWNER_NAME))
self.browser.getControl(name='password').value = SITE_OWNER_PASSWORD
self.browser.getControl(name='confirm').value = SITE_OWNER_PASSWORD
self.browser.getForm().submit()
self.assertEquals(
self.browser.url,
'%s/acl_users/users/manage_users?manage_tabs_message=password+updated' % (
self.layer['app'].absolute_url()))

0 comments on commit 3ffaf6b

Please sign in to comment.